Django 框架 - 資料庫操作
資料庫
ORM框架
O是object,也就類物件的意思,R是relation,翻譯成中文是關係,也就是關係資料庫中資料表的意思,M是mapping,是對映的意思。在ORM框架中,它幫我們把類和資料表進行了一個對映,可以讓我們通過類和類物件就能操作它所對應的表格中的資料。ORM框架還有一個功能,它可以根據我們設計的類自動幫我們生成資料庫中的表格,省去了我們自己建表的過程。
django中內嵌了ORM框架,不需要直接面向資料庫程式設計,而是定義模型類,通過模型類和物件完成資料表的增刪改查操作。
使用django進行資料庫開發的步驟如下:
- 配置資料庫連線資訊
- 在models.py中定義模型類
- 遷移
- 通過類和物件完成資料增刪改查操作
配置
在settings.py中儲存了資料庫的連線配置資訊,Django預設初始配置使用sqlite資料庫。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'db.sqlite3'),
}
}
-
使用MySQL資料庫首先需要安裝驅動程式
pip install PyMySQL
-
在Django的工程同名子目錄的__init__.py檔案中新增如下語句
from pymysql import install_as_MySQLdb install_as_MySQLdb()
作用是讓Django的ORM能以mysqldb的方式來呼叫PyMySQL。
-
修改DATABASES配置資訊
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'HOST': '127.0.0.1', # 資料庫主機 'PORT': 3306, # 資料庫埠
-
在MySQL中建立資料庫
create database django_demo default charset=utf8;
定義模型類
- 模型類被定義在"應用/models.py"檔案中。
- 模型類必須繼承自Model類,位於包django.db.models中。
1 定義
1) 資料庫表名
模型類如果未指明表名,Django預設以 小寫app應用名_小寫模型類名 為資料庫表名。
可通過db_table 指明資料庫表名。
2) 關於主鍵
django會為表建立自動增長的主鍵列,每個模型只能有一個主鍵列,如果使用選項設定某屬性為主鍵列後django不會再建立自動增長的主鍵列。
預設建立的主鍵列屬性為id,可以使用pk代替,pk全拼為primary key。
3) 屬性命名限制
-
不能是python的保留關鍵字。
-
不允許使用連續的下劃線,這是由django的查詢方式決定的。
-
定義屬性時需要指定欄位型別,通過欄位型別的引數指定選項,語法如下:
屬性=models.欄位型別(選項)
4)欄位型別
型別 | 說明 |
---|---|
AutoField | 自動增長的IntegerField,通常不用指定,不指定時Django會自動建立屬性名為id的自動增長屬性 |
BooleanField | 布林欄位,值為True或False |
NullBooleanField | 支援Null、True、False三種值 |
CharField | 字串,引數max_length表示最大字元個數 |
TextField | 大文字欄位,一般超過4000個字元時使用 |
IntegerField | 整數 |
DecimalField | 十進位制浮點數, 引數max_digits表示總位數, 引數decimal_places表示小數位數 |
FloatField | 浮點數 |
DateField | 日期, 引數auto_now表示每次儲存物件時,自動設定該欄位為當前時間,用於"最後一次修改"的時間戳,它總是使用當前日期,預設為False; 引數auto_now_add表示當物件第一次被建立時自動設定當前時間,用於建立的時間戳,它總是使用當前日期,預設為False; 引數auto_now_add和auto_now是相互排斥的,組合將會發生錯誤 |
TimeField | 時間,引數同DateField |
DateTimeField | 日期時間,引數同DateField |
FileField | 上傳檔案欄位 |
ImageField | 繼承於FileField,對上傳的內容進行校驗,確保是有效的圖片 |
5) 選項
選項 | 說明 |
---|---|
null | 如果為True,表示允許為空,預設值是False |
blank | 如果為True,則該欄位允許為空白,預設值是False |
db_column | 欄位的名稱,如果未指定,則使用屬性的名稱 |
db_index | 若值為True, 則在表中會為此欄位建立索引,預設值是False |
default | 預設 |
primary_key | 若為True,則該欄位會成為模型的主鍵欄位,預設值是False,一般作為AutoField的選項使用 |
unique | 如果為True, 這個欄位在表中必須有唯一值,預設值是False |
null是資料庫範疇的概念,blank是表單驗證範疇的
6) 外來鍵
在設定外來鍵時,需要通過on_delete選項指明主表刪除資料時,對於外來鍵引用表資料如何處理,在django.db.models中包含了可選常量:
-
CASCADE 級聯,刪除主表資料時連通一起刪除外來鍵表中資料
-
PROTECT 保護,通過丟擲ProtectedError異常,來阻止刪除主表中被外來鍵應用的資料
-
SET_NULL 設定為NULL,僅在該欄位null=True允許為null時可用
-
SET_DEFAULT 設定為預設值,僅在該欄位設定了預設值時可用
-
SET() 設定為特定值或者呼叫特定方法,如
from django.conf import settings from django.contrib.auth import get_user_model from django.db import models def get_sentinel_user(): return get_user_model().objects.get_or_create(username='deleted')[0] class MyModel(models.Model): user = models.ForeignKey( settings.AUTH_USER_MODEL, on_delete=models.SET(get_sentinel_user), )
-
DO_NOTHING 不做任何操作,如果資料庫前置指明級聯性,此選項會丟擲IntegrityError異常
2 遷移
將模型類同步到資料庫中。
1)生成遷移檔案
python manage.py makemigrations
2)同步到資料庫中
python manage.py migrate
演示工具
shell工具
Django的manage工具提供了shell命令,幫助我們配置好當前工程的執行環境(如連線好資料庫等),以便可以直接在終端中執行測試python語句。
通過如下命令進入shell
python manage.py shell
檢視MySQL資料庫日誌
檢視mysql資料庫日誌可以檢視對資料庫的操作記錄。 mysql日誌檔案預設沒有產生,需要做如下配置:
sudo vi /etc/mysql/mysql.conf.d/mysqld.cnf
把68,69行前面的#去除,然後儲存並使用如下命令重啟mysql服務。
sudo service mysql restart
使用如下命令開啟mysql日誌檔案。
tail -f /var/log/mysql/mysql.log # 可以實時檢視資料庫的日誌內容
# 如提示需要sudo許可權,執行
# sudo tail -f /var/log/mysql/mysql.log
資料庫操作——增、刪、改、查
增加
- save
- 先建立模型類物件,執行物件的 save() 方法儲存到資料庫中
- create
- 通過 模型類.objects.create() 儲存,建立完直接儲存
查詢
基本查詢
- get 查詢單一結果,如果不存在會丟擲 模型類.DoesNotExist 異常
- all 查詢多個結果
- coutn 查詢結果數量
過濾查詢
實現 SQL 中的 where 功能
- filter 過濾出多個結果
- exclude 排除掉符合條件剩下的結果
- get 過濾單一結果
對於過濾條件的使用,上述三個方法相同,僅以 filter 進行講解
過濾條件的表達語法如下:
屬性名稱__比較運算子=值
# 屬性名稱和比較運算子間使用兩個下劃線,所以屬性名不能包括多個下劃線
- 相等
- exact: 表示判等
- 模糊查詢
- contains:是否包含 如果要包含 % 無序轉義,直接寫即可
- startswith、endswith:以指定值開頭或結尾
- 以上執行符都區分大小寫,在這些運算子前加上 i 表示不區分大小寫
- 空查詢
- isnull:是否為 null
- 範圍查詢
- in:是否包含在範圍內
- 比較查詢
- gt:大於
- gte:大於等於
- lt:小於
- lte:小於等於
- 不等於的運算子,使用 exclude() 過濾器
- 日期查詢
- year、month、day、week_day、hour、minute、second:對日期時間型別的屬性進行運算。
- F 物件
- 之前的查詢都是物件的屬性和常量值比較,使用 F物件可以實現兩個屬性直接進行比較
- 語法:
F("屬性名")
- 可以在 F 物件上使用算數運算
- Q 物件
- 對個過濾器逐個呼叫表示邏輯與關係,同 sql 語句中 where 部分的 and 關鍵字
- 如果需要實現邏輯或or的查詢,需要使用Q()物件結合|運算子,Q物件被義在django.db.models中
- 語法:
Q(屬性名__運算子=值)
- Q物件可以使用 &、| 連線,& 表示邏輯與,| 表示邏輯或。
- Q物件前可以使用~操作符,表示非not。
聚合函式
使用aggregate()過濾器呼叫聚合函式。聚合函式包括:Avg 平均,Count 數量,Max 最大,Min 最小,Sum 求和,被定義在django.db.models中。
- aggregaye 的返回值是一個字典型別
- 使用 count 時一般不使用 aggergate() 過濾器
排序
使用 order_by 對結果進行排序
關聯查詢
-
從一到多的訪問語法
- 一對應的模型類物件.多對應的模型類名小寫_set
b = BookInfo.objects.get(id=1) b.heroinfo_set.all()
-
從多到一的訪問語法
- 多對應的模型類物件.多對應的模型類中關係類屬性名
h = HeroInfo.objects.get(id=1) h.hbook
-
訪問一對應的模型類關聯物件的 id 語法
- 多對應的模型類物件.關聯類屬性_id
h = HeroInfo.objects.get(id=1) h.hbook_id
關聯過濾查詢
由多模型類條件查詢一模型類資料:
語法如下:
關聯模型類名小寫__屬性名__條件運算子=值
注意:如果沒有"__運算子"部分,表示等於。
例:
查詢圖書,要求圖書英雄為"孫悟空"
BookInfo.objects.filter(heroinfo__hname='孫悟空')
查詢圖書,要求圖書中英雄的描述包含"八"
BookInfo.objects.filter(heroinfo__hcomment__contains='八')
由一模型類條件查詢多模型類資料:
語法如下:
一模型類關聯屬性名__一模型類屬性名__條件運算子=值
注意:如果沒有"__運算子"部分,表示等於。
修改
- save
- 修改模型類物件的屬性,然後執行 save() 方法
- update
- 使用模型類.objects.filter().update() ,會返回受影響的行數
- 使用模型類.objects.filter().update() ,會返回受影響的行數
刪除
- 模型類物件 delete
- 模型類.objects.filter().delete()
查詢集 QuerySet
概念
Django的ORM中存在查詢集的概念。
查詢集,也稱查詢結果集、QuerySet,表示從資料庫中獲取的物件集合。
當呼叫如下過濾器方法時,Django會返回查詢集(而不是簡單的列表):
- all():返回所有資料。
- filter():返回滿足條件的資料。
- exclude():返回滿足條件之外的資料。
- order_by():對結果進行排序。
對查詢集可以再次呼叫過濾器進行過濾,如
BookInfo.objects.filter(bread__gt=30).order_by('bpub_date')
也就意味著查詢集可以含有零個、一個或多個過濾器。過濾器基於所給的引數限制查詢的結果。
從SQL的角度講,查詢集與select語句等價,過濾器像where、limit、order by子句。
判斷某一個查詢集中是否有資料:
- exists():判斷查詢集中是否有資料,如果有則返回True,沒有則返回False。
兩大特性
惰性執行
建立查詢集不會訪問資料庫,直到呼叫資料時,才會訪問資料庫,呼叫資料的情況包括迭代、序列化、與if合用
例如,當執行如下語句時,並未進行資料庫查詢,只是建立了一個查詢集qs
qs = BookInfo.objects.all()
繼續執行遍歷迭代操作後,才真正的進行了資料庫的查詢
for book in qs:
print(book.btitle)
快取
使用同一個查詢集,第一次使用時會發生資料庫的查詢,然後Django會把結果快取下來,再次使用這個查詢集時會使用快取的資料,減少了資料庫的查詢次數。
限制查詢集
可以對查詢集進行取下標或切片操作,等同於sql中的limit和offset子句。
注意:不支援負數索引。
對查詢集進行切片後返回一個新的查詢集,不會立即執行查詢。
如果獲取一個物件,直接使用[0],等同於[0:1].get(),但是如果沒有資料,[0]引發IndexError異常,[0:1].get()如果沒有資料引發DoesNotExist異常。
示例:獲取第1、2項,執行檢視。
qs = BookInfo.objects.all()[0:2]
管理器 Manager
管理器是 Django 的模型進行資料庫操作的介面,Django 應用的每個模型類都擁有至少一個管理器。
我們在通過模型類的objects屬性提供的方法操作資料庫時,即是在使用一個管理器物件objects。當沒有為模型類定義管理器時,Django會為每一個模型類生成一個名為objects的管理器,它是models.Manager類的物件。
自定義管理器
我們可以自定義管理器,並應用到我們的模型類上。
注意:一旦為模型類指明自定義的過濾器後,Django不再生成預設管理物件objects。