django系列5.1--ORM對數據庫的操做

Django--—ORM數據庫操做(圖書管理系統基本實例)html

一.基本知識

MVC模式(Model–view–controller)是軟件工程中的一種軟件架構模式,把軟件系統分爲三個基本部分:模型(Model)、視圖(View)和控制器(Controller)。python

ORM:對象關係映射(Object Relational Mapping,簡稱ORM,或O/RM,或O/R mapping),是一種程序技術,用於實現面向對象編程語言裏不一樣類型系統的數據之間的轉換 。 從效果上說,它實際上是建立了一個可在編程語言裏使用的-–「虛擬對象數據庫」。mysql

FBV (function base views)就是在視圖裏使用函數處理請求。linux

CBV(class base views) 就是在視圖裏使用類處理請求。git

<br/>sql

二.爲項目添加新app

注意新添加app時應在配置文件中的INSTALLED_APPS中寫入咱們建立的app名稱數據庫

INSTALLED_APPS = [
    'django.contrib.admin',  #這是django給你提供的一些特殊功能的配置(應用,只是我們看不到),也在應用這裏給配置的,這些功能若是你註銷了,那麼咱們執行同步數據庫指令以後,就不會生成那些django自帶的表了。由於執行數據庫同步語句的時候,django會找這裏面全部的應用,找到他們的models來建立表
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    "book"  #直接寫app的名字也行,寫'app01.apps.App01Config'也行
]

<br/>django

三.建立與數據庫的鏈接

1.此時首先應創建一個mysql數據庫,這裏我建立的數據庫名爲orm<br/>編程

2.settings.py文件中配置數據庫鏈接,(建立項目時有默認的語句,找到DATABASES後修改補全便可)session

# Database
# https://docs.djangoproject.com/en/1.11/ref/settings/#databases

DATABASES = {
    'default': {
        'ENGINE': 'django.db.backends.mysql',  # 鏈接的數據庫類型
        'NAME': 'orm',  # 數據庫名稱
        'USER':'root',  # 用戶名
        'PASSWORD':'123',
        'HOST':'127.0.0.1',
        'PORT':3306
        # 'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),  # 建立項目時默認用的數據庫類型
    }
}

sqlite數據庫下的db.sqlite3則是項目自動建立 USER和PASSWORD分別是數據庫的用戶名和密碼。設置完後,再啓動咱們的Django項目前,咱們須要激活咱們的mysql。而後,啓動項目,會報錯:no module named MySQLdb 。這是由於django默認你導入的驅動是MySQLdb,但是MySQLdb 對於py3有很大問題,因此咱們須要的驅動是PyMySQL 因此,咱們只須要找到項目名文件下的__init__.py,在裏面寫入:

<br/>

3.在項目app中的__init__.py 輸入下面代碼

import pymysql

pymysql.install_as_MySQLdb()

<br/>

4.建立數據庫表.先建立模式,項目目錄下的models.py

from django.db import models

# Create your models here.
class Book(models.Model):
    id = models.AutoField(primary_key=True)
    title = models.CharField(max_length=32)
    pub_date = models.DateField()
    price = models.DecimalField(max_digits=8,decimal_places=2)
    publish = models.CharField(max_length=20)

    def __str__(self):  # 這裏用來之後對數據庫操做時在控制檯輸出titile名稱
        return self.title

<br/>

5.須要在terminal中輸入兩行命令

python3 manage.py makemigrations   # 建立腳本
python3 manage.py migrate   # 遷移

<br/>

6.查看執行的sql語句

在settings.py文件中加入

查看數據庫執行代碼
LOGGING = {
    'version': 1,
    'disable_existing_loggers': False,
    'handlers': {
        'console':{
            'level':'DEBUG',
            'class':'logging.StreamHandler',
        },
    },
    'loggers': {
        'django.db.backends': {
            'handlers': ['console'],
            'propagate': True,
            'level':'DEBUG',
        },
    }
}

<br/>

四.單表操做

在views.py中添加對數據庫的操做語句

#在邏輯代碼中導入你要操做的表
from app import models

def add_book(request):
    '''
    添加表記錄
    :param request: http請求信息
    :return:
    '''
    models.Book(title='人間失格',price=12,pub_date='2012-12-12',publish='文學出版社')

1.添加表記錄

方式1:實例化對象就是一條表記錄

from app import models


obj = models.Book(title='復活',price=12,pub_date='2012-12-12',publish='小出版社')
obj.save()

方式2:(咱們通常使用方式二添加)

models.Book.objects.create(title='復活',price=12,pub_date='2012-12-12',publish='小出版社')

<br/>

2.查詢表記錄

查詢全部的記錄:

obj = models.Book.objects.all()

使用values的結果:

obj = models.Book.objects.all().values()
# <QuerySet [{'id': 1, 'title': '雪國列車2', 'pub_date': datetime.date(2012, 12, 1),

<br/>

經常使用的查詢API:

<1> all():                  查詢全部結果,結果是queryset類型

<2> filter(**kwargs):       它包含了與所給篩選條件相匹配的對象,結果也是queryset類型 Book.objects.filter(title='linux',price=100) #裏面的多個條件用逗號分開,而且這幾個條件必須都成立,是and的關係,or關係的咱們後面再學,直接在這裏寫是搞不定or的

<3> get(**kwargs):          返回與所給篩選條件相匹配的對象,不是queryset類型,是行記錄對象,返回結果有且只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。捕獲異常try。  Book.objects.get(id=1)

<4> exclude(**kwargs):      排除的意思,它包含了與所給篩選條件不匹配的對象,沒有不等於的操做昂,用這個exclude,返回值是queryset類型 Book.objects.exclude(id=6),返回id不等於6的全部的對象,或者在queryset基礎上調用,Book.objects.all().exclude(id=6)            

<5>  order_by(*field):       queryset類型的數據來調用,對查詢結果排序,默認是按照id來升序排列的,返回值仍是queryset類型
models.Book.objects.all().order_by('price','id') #直接寫price,默認是按照price升序排列,按照字段降序排列,就寫個負號就好了order_by('-price'),order_by('price','id')是多條件排序,按照price進行升序,price相同的數據,按照id進行升序

<6> reverse():              queryset類型的數據來調用,對查詢結果反向排序,返回值仍是queryset類型

<7> count():                queryset類型的數據來調用,返回數據庫中匹配查詢(QuerySet)的對象數量。

<8> first():                queryset類型的數據來調用,返回第一條記錄 Book.objects.all()[0] = Book.objects.all().first(),獲得的都是model對象,不是queryset

<9> last():                queryset類型的數據來調用,返回最後一條記錄

<10> exists():              queryset類型的數據來調用,若是QuerySet包含數據,就返回True,不然返回False.   空的queryset類型數據也有布爾值True和False,可是通常不用它來判斷數據庫裏面是否是有數據,若是有大量的數據,你用它來判斷,那麼就須要查詢出全部的數據,效率太差了,用count或者exits例:all_books = models.Book.objects.all().exists() #翻譯成的sql是SELECT (1) AS `a` FROM `app01_book` LIMIT 1,就是經過limit 1,取一條來看看是否是有數據

<11> values(*field):        用的比較多,queryset類型的數據來調用,返回一個ValueQuerySet——一個特殊的QuerySet,運行後獲得的並非一系列.model的實例化對象,而是一個可迭代的字典序列,只要是返回的queryset類型,就能夠繼續鏈式調用queryset類型的其餘的查找方法,其餘方法也是同樣的。

<12> values_list(*field):   它與values()很是類似,它返回的是一個元組序列,values返回的是一個字典序列
<13> distinct():            values和values_list獲得的queryset類型的數據來調用,從返回結果中剔除重複紀錄

<br/>

雙下劃線的單表查詢

Book.objects.filter(price__in=[100,200,300]) #price值等於這三個裏面的任意一個的對象
Book.objects.filter(price__gt=100)  #大於,大於等因而price__gte=100,別寫price>100,這種參數不支持
Book.objects.filter(price__lt=100)  # 小於 同大於,不包含邊界值
Book.objects.filter(price__range=[100,200])  #sql的between and,大於等於100,小於等於200
Book.objects.filter(title__contains="python")  #title值中包含python的
Book.objects.filter(title__icontains="python") #不區分大小寫
Book.objects.filter(title__startswith="py") #以什麼開頭,istartswith  不區分大小寫
Book.objects.filter(pub_date__year=2012)  # 日期查詢,年份爲2012的數據

<br/>

關於value的用法

all_books = models.Book.objects.all().values('id','title')
print(all_books) 
#<QuerySet [{'title': 'linux', 'id': 6}, {'title': '你好', 'id': 7}, {'title': 'linux', 'id': 8}, {'title': 'xxx', 'id': 9}, {'title': 'gogogo', 'id': 10}]>

    '''
        values作的事情:
        ret = [] #queryset類型
        for obj in Book.objects.all():
            temp = {  #元素是字典類型
                'id':obj.id,
                'title':obj.title
            }
            ret.append(temp)

    '''

</br>

關於時間問題:日期查詢

all_books = models.Book.objects.filter(pub_date__year=2012)   # 找2012年的全部書籍
all_books = models.Book.objects.filter(pub_date__year__gt=2012)  # 找大於2012年的全部書籍
all_books = models.Book.objects.filter(pub_date__year=2019,pub_date__month=2)  # 找2019年月份的全部書籍,若是明明有結果,你卻查不出結果,是由於mysql數據庫的時區和我們django的時區不一樣致使的,瞭解一下就好了,你須要作的就是將django中的settings配置文件裏面的USE_TZ = True改成False,就能夠查到結果了,之後這個值就改成False,並且就是由於我們用的mysql數據庫纔會有這個問題,其餘數據庫沒有這個問題。

當查詢日期出現問題時:

將settings.py中最下面的USE_TZ = False改成True

USE_TZ = True

不是跨時區的應用,不須要考慮時區問題,就將這個值改成False,mysql是對時區不敏感,django往mysql裏面出數據的時候,若是這裏的值爲True,那麼將讓mysql強制使用UTC時間,那麼咱們存儲進入的時間,當你查詢的時候,你就會發現,時間晚了8小時,也就是說你存時間的時候被改成了UTC時間,本地是東八區,比UTC時間多8小時

<br/>

3.修改表記錄

update只能是QuerySet類型才能調用,model對象不能直接調用更新方法,因此使用get方法獲取對象的時候是不能使用update方法的

Book.objects.filter(title__startswith="復活").update(price=12)

注意:

<input type="date" class="form-control" id="book_pub_date" placeholder="出版日期" name="book_pub_date" value="{{ edit_obj.pub_date|date:'Y-m-d' }}">

type='date'的input標籤,value的值必須是'Y-m-d'的格式,這個標籤才能認識並被賦值,因此,要經過date過濾給它改變格式。

<br/>

4.刪除表記錄

刪除方法.delete()的調用者能夠是一個model對象,也能夠是一個queryset集合.它運行時當即刪除對象而不返回任何值,也能夠一次刪除多個對象.每一個queryset都有一個delete()方法

models.Book.objects.filter(title='復活').delete()  # 刪除標題爲復活的Book對象

任何狀況下,QuerySet中的delete()方法都只使用一條SQL語句一次性刪除全部對象,而並非分別刪除誒個對象,若是想使用model中自定義的delete()方法,就要自行調用每一個對象的delete()方法(例如,遍歷 QuerySet,在每一個對象上調用 delete()方法),而不是使用 QuerySet 中的 delete()方法。

在Django刪除對象時,會模仿SQL約束 ON DELETE CASCDE的行爲(刪除一個對象時也會刪除與它相關聯的外鍵對象)

b = Blog.objects.get(pk=1)
# This will delete the Blog and all of its Entry objects.
b.delete()

delete() 方法是 QuerySet 上的方法,但並不適用於 Manager 自己。這是一種保護機制,是爲了不意外地調用 Entry.objects.delete() 方法致使 全部的 記錄被誤刪除。若是你確認要刪除全部的對象,那麼你必須顯式地調用:

Entry.objects.all().delete()
相關文章
相關標籤/搜索