定義類屬性
Django會(huì)自動(dòng)創(chuàng)建
自動(dòng)增長的主鍵字段
每個(gè)模型只能有一個(gè)主鍵
如果使用選項(xiàng)
設(shè)置某屬性為主鍵
字段后django不會(huì)再自動(dòng)創(chuàng)建
自動(dòng)增長的主鍵
自動(dòng)創(chuàng)建的主鍵列屬性名為id
使用時(shí)可以使用pk
代替 pk全拼為primary key
注意:pk是主鍵的別名螟加,若主鍵名為id2徘溢,那么pk是id2的別名
屬性命名限制
不能是python的保留關(guān)鍵字
不允許使用連續(xù)的下劃線 這是由django的查詢方式?jīng)Q定的
定義屬性
時(shí)需要指定字段類型
通過字段類型的參數(shù)指定選項(xiàng)
語法如下:
屬性=models.字段類型(選項(xiàng))
字段類型
使用時(shí)需要引入django.db.models
包
字段類型如下:
AutoField
: 自動(dòng)增長的IntegerField 不指定值時(shí)Django會(huì)自動(dòng)創(chuàng)建屬性名為id的自動(dòng)增長屬性
BooleanField
: 布爾字段 值為 True或False
NullBooleanField
: 支持Null True False三種值
CharField(max_length=num)
: 字符串 必須設(shè)置長度
參數(shù)max_length表示最大字符數(shù)
TextField
: 大文本 一般超過4000時(shí)使用
IntegerField
: 整數(shù)
DecimalField(max_digits=None, decimal_places=None)
: 可以指定精度的十進(jìn)制浮點(diǎn)數(shù)
參數(shù)max_digits 表示總位數(shù)
參數(shù)decimal_places 表示小數(shù)位數(shù)
FloatField
: 浮點(diǎn)數(shù)
DateField([auto_now=False,auto_now_add=False])
: 日期
參數(shù)auto_now表示每次保存對(duì)象時(shí) 自動(dòng)設(shè)置當(dāng)前時(shí)間默認(rèn)為false
參數(shù)auto_now_add表示第一次被創(chuàng)建時(shí)自動(dòng)設(shè)置當(dāng)前時(shí)間flase
參數(shù)auto_now_add 和auto_now 是相互排斥的 組合將會(huì)發(fā)生錯(cuò)誤
TimeField
: 時(shí)間 參數(shù)和DateField一樣
DateTimeField
: 日期時(shí)間 參數(shù)同DateField一樣
FileField
: 上傳文件字段 以二進(jìn)制的形式
ImageField
: 繼承于FileField 對(duì)上傳內(nèi)容進(jìn)行校驗(yàn) 確保是有效的圖片
DecimalField 精度比 FloatField 要高 這是由底層存儲(chǔ)方式?jīng)Q定的
選項(xiàng)
通過選項(xiàng)實(shí)現(xiàn)對(duì)字段的約束 選項(xiàng)如下:
null
: 如果為True 表示允許為空 默認(rèn)False
blank
: 如果是True 表示允許為空白 默認(rèn)False
null是數(shù)據(jù)庫范疇的概念 blank是表單驗(yàn)證的范疇(如果僅null=True 在后臺(tái)輸入表單更新字段時(shí)表單驗(yàn)證會(huì)提示不能為空)
primary_key
: 若為True 則表示字段會(huì)成為模型的主鍵字段 默認(rèn)值False 一般作為AutoField的選項(xiàng)使用
如果使用選項(xiàng)設(shè)置某些屬性為主鍵字段后 Django將不會(huì)創(chuàng)建自動(dòng)增長的名為id的主鍵字段
unique
: 若為True 則表示這個(gè)字段的記錄的值必須唯一 默認(rèn)是False
db_index
: 若為True 則表示會(huì)為此字段創(chuàng)建索引 默認(rèn)值為False
default
: 默認(rèn)值 可以是值或可調(diào)用對(duì)象
db_column
: 表中字段的名稱 如果未指定 則使用類屬性的名稱
只限于數(shù)據(jù)庫表中的名字 操作模型類還是使用類屬性的名字
字段查詢
查詢 通過 模型類.objects.過濾器函數(shù)()
字段查詢 通過 模型類.objects.過濾器函數(shù)(屬性名稱__比較運(yùn)算符=值)
過濾器函數(shù)
get()
返回滿足條件的對(duì)象 是一個(gè)普通對(duì)象
- 如果查詢到多條數(shù)據(jù)則拋出
MultipleObjectsReturned
- 查詢不到內(nèi)容則拋出
DoesNotExist
all()
返回所有對(duì)象 是一個(gè)QuerySet對(duì)象
filter()
返回滿足條件的對(duì)象 是一個(gè)QuerySet對(duì)象
exclude()
返回不滿足條件的對(duì)象 是一個(gè)QuerySet對(duì)象
order_by()
返回QuerySet對(duì)象的排序結(jié)果 是一個(gè)QuerySet對(duì)象
aggregate(聚合)
返回QuerySet對(duì)象聚合函數(shù)后的結(jié)果 是一個(gè)Python字典
count()
返回結(jié)果對(duì)象或QuerySet對(duì)象的統(tǒng)計(jì)個(gè)數(shù) 是一個(gè)整型 注意: 這個(gè)函數(shù)沒有參數(shù)
exists()
返回QuerySet對(duì)象是否有數(shù)據(jù) 是一個(gè)布爾類型(True非空
False空
) 注意:這個(gè)函數(shù)沒有參數(shù)
QertySet 對(duì)象可以繼續(xù)使用以上過濾器函數(shù)查詢
條件運(yùn)算符
等查詢
判等 __exact
BookInfo.objects.get(id__exact=1)
簡寫為:
BookInfo.objects.get(id=1)
模糊查詢
包含 __contains
BookInfo.objects.filter(btitle__contains="傳")
開頭或結(jié)尾 __startswith | __endswith
BookInfo.objects.filter(btitle__startswith="天")
BookInfo.objects.filter(btitle__endswith="部")
以上運(yùn)算符都區(qū)分大小寫吞琐,在這些運(yùn)算符前加上
i
表示不區(qū)分大小寫,如iexact
然爆、icontains
站粟、istartswith
、iendswith
空查詢
空 __isnull=True
BookInfo.objects.filter(btitle__isnull=False)
范圍查詢
范圍 __in=[]
BookInfo.objects.filter(id__in=[1,3,5])
比較查詢
gt
大于 lt
小于 gte
大于等于 lte
小于等于
BookInfo.objects.filter(id__gt=3)
不等于 exclude()
過濾器
BookInfo.objects.exclude(id__exact=3)
日期查詢
year曾雕、month奴烙、day、week_day剖张、hour切诀、minute、second
BookInfo.objects.filter(bpub_date__year=1980)
from datetime import date
BookInfo.objects.filter(bpub_date__gt = date(1980,1,1))
排序
默認(rèn)從小到大
ASC 輸入-
從大到小 DESC
order_by
的參數(shù)必須是字符串類型
可以對(duì)QuerySet查詢集使用
排序 order_by()
過濾器
BookInfo.objects.all().order_by("id", "btitle")
BookInfo.objects.filter(id__gt=3).order_by("-bread")
F對(duì)象
F(屬性名)
用于類屬性之間
的比較
F對(duì)象內(nèi)輸入的必須是字符串
F對(duì)象可以進(jìn)行運(yùn)算符運(yùn)算
from django.db.models import F
例:查詢閱讀量大于評(píng)論量的對(duì)象
BookInfo.objects.filter(bread__gt=F("bcomment"))
例: 查詢閱讀量大于 二倍的評(píng)論量
BookInfo.objects.filter(bread__gt=F("bcomment")*2)
Q對(duì)象
Q(屬性名__條件運(yùn)算符=值)
用于查詢時(shí)條件之間的邏輯關(guān)系
使用Q創(chuàng)建一個(gè)對(duì)象在Q對(duì)象前輸入 &
|
~
表示 and
or
not
from django.db.models import Q
and
BookInfo.objects.filter(id=1, btitle="天龍八部")
或
BookInfo.objects.filter(Q(id=1)&Q(btitle="天龍八部"))
or
BookInfo.objects.filter(Q(id=1)|Q(btitle="雪山飛狐"))
not
BookInfo.objects.exclude(id__gt=3)
或
BookInfo.objects.filter(~Q(id__gt=3))
一般在需要使用or關(guān)系時(shí)才使用Q對(duì)象
聚合函數(shù)
aggregate()
過濾器來調(diào)用聚合函數(shù)
返回一個(gè)字典{'聚合類名小寫__屬性名':值}
格式如: {'sum__bread':3}
使用前 需要從django.db.models
導(dǎo)入聚合類
聚合函數(shù)的參數(shù)必須是字符串
from django.db.models import Sum, Count, Max, Min, Avg
例:查詢所有圖書的數(shù)目
BookInfo.objects.all().aggregate(Count("id"))
返回{'id__count': 8}
例:查詢所有圖書閱讀量的總和
BookInfo.objects.all().aggregate(Sum("bread"))
返回{'bread__sum': 126}
count()過濾器
統(tǒng)計(jì)滿足條件的數(shù)據(jù)數(shù)目
返回值是一個(gè)整型
例:統(tǒng)計(jì)所有圖書的數(shù)目
BookInfo.objects.all().count()
例:統(tǒng)計(jì)ID大于3的所有圖書數(shù)目
BookInfo.objects.filter(id__gt=3).count()
查詢集
在管理器
上調(diào)用某些過濾器方法會(huì)返回查詢集
查詢集結(jié)果可以有零個(gè)
一個(gè)
或 多個(gè)
從Sql的角度搔弄,查詢集和select語句等價(jià)幅虑,過濾器像where和limit子句
QuerySet對(duì)象
在Django中叫做查詢集
表示查詢到的多條數(shù)據(jù)表記錄的集合
QuerySet可以遍歷
且 可以寫入多個(gè)
條件
QuerySet對(duì)象可以繼續(xù)應(yīng)用all
filter
excloud
order_by
等所有過濾器
BookInfo.objects
管理器 是一個(gè)Manager的對(duì)象
BookInfo.objects.get(id=1)
表示一條記錄
BookInfo.objects.all()
|filter()
|exclude()
|order_by(id)
表示多條數(shù)據(jù) 是一個(gè)QertySet對(duì)象
對(duì)任何管理器.all()
查詢的結(jié)果使用過濾器時(shí)可以省略all() 如: BookInfo.objects.count()
返回單個(gè)值的過濾器如下
-
get():返回單個(gè)滿足條件的對(duì)象
- 如果未找到會(huì)引發(fā)
模型類.DoesNotExist
異常 - 如果多條被返回會(huì)引發(fā)
模型類.MultipleObjectsReturned
異常
- 如果未找到會(huì)引發(fā)
count():返回當(dāng)前查詢結(jié)果的總條數(shù)
aggregate():聚合,返回一個(gè)字典
返回查詢集的過濾器如下
- all():返回所有數(shù)據(jù)顾犹。
- filter():返回滿足條件的數(shù)據(jù)倒庵。
- exclude():返回滿足條件之外的數(shù)據(jù),相當(dāng)于sql語句中where部分的not關(guān)鍵字炫刷。
- order_by():對(duì)結(jié)果進(jìn)行排序擎宝。
判斷某一個(gè)查詢集中是否有數(shù)據(jù)
- exists():判斷查詢集中是否有數(shù)據(jù),如果有則返回True浑玛,沒有則返回False绍申。
兩大特性
1.惰性查詢
只有在實(shí)際使用
時(shí)才真正的對(duì)數(shù)據(jù)庫進(jìn)行操作
(創(chuàng)建查詢集對(duì)象時(shí) 不實(shí)際操作數(shù)據(jù)表)
而真正調(diào)用數(shù)據(jù)表的情況包括迭代
、序列化
锄奢、與if合用
(針對(duì)查詢集對(duì)象使用以上操作時(shí)才實(shí)際操作數(shù)據(jù)表)
2.緩存
每個(gè)查詢集都包含一個(gè)緩存
來最小化對(duì)數(shù)據(jù)庫的訪問
第一次
使用時(shí)查詢數(shù)據(jù)庫 并把結(jié)果緩存
起來
再次
使用時(shí)不會(huì)查詢數(shù)據(jù)庫而是使用緩存的結(jié)果
books = BookInfo.objects.filter(btitle__isnull) 實(shí)際不查詢數(shù)據(jù)庫
[book for book in books] 第一次使用 實(shí)際查詢數(shù)據(jù)庫
[book for book in books] 再次使用 實(shí)際不查詢數(shù)據(jù)庫
限制查詢集
可以對(duì)查詢集進(jìn)行取下標(biāo)或切片操作失晴,等同于sql中的limit和offset子句
但是不同于列表 不可以使用負(fù)值切片和取值
例: 獲取1,2兩個(gè)對(duì)象 返回一個(gè)QuerySet 查詢集
BookInfo.objects.all()[0:2]
注意
獲取一個(gè)對(duì)象使用QuerySet[0]
等價(jià)于 QuerySet[0:1].get()
QuerySet[0]
返回普通對(duì)象QuerySet[0:1]
返回只有一個(gè)值的QuerySet對(duì)象
對(duì)只有一個(gè)值的查詢集對(duì)象使用get()
會(huì)得到一個(gè)普通對(duì)象
如果沒有數(shù)據(jù),QuerySet[0]
引發(fā)IndexError
異常
如果沒有數(shù)據(jù)拘央,QuerySet[0:1].get()
引發(fā)DoesNotExist
異常
模型類關(guān)系
一對(duì)應(yīng)的類叫做一類
多對(duì)應(yīng)的類叫做多類
把用來建立關(guān)聯(lián)的類屬性叫做關(guān)聯(lián)屬性
關(guān)系字段類型
關(guān)系型數(shù)據(jù)庫的關(guān)系包括三種類型:
ForeignKey:一對(duì)多,將字段定義在多的一端
中
ManyToManyField:多對(duì)多书在,將字段定義在任意一端
中
OneToOneField:一對(duì)一灰伟,將字段定義在任意一端
中
可以維護(hù)遞歸的關(guān)聯(lián)關(guān)系,使用"self"
指定儒旬,詳見"自關(guān)聯(lián)"
一對(duì)多關(guān)系
表1的某條記錄對(duì)應(yīng)表2的多條記錄
表2的多條記錄對(duì)應(yīng)表1的一條記錄
設(shè)置ForeignKey
到多類
中
hbook = models.models.ForignKey("一類表名")
多對(duì)多關(guān)系
表1的多條記錄對(duì)應(yīng)表1的多條記錄
表2的多條記錄對(duì)應(yīng)表1的多條記錄
設(shè)置ManyToManyField
到任意類
中
ntype = models.ManyToManyField("多類表名")
一對(duì)一關(guān)系
表1的某條記錄對(duì)應(yīng)表2的某條記錄
表2的某條記錄對(duì)應(yīng)表1的某條記錄
設(shè)置OneToOneField
到任意類
中
ebasic = models.OneToOneField("一類表名")
關(guān)聯(lián)查詢(一對(duì)多)
實(shí)現(xiàn)類似于inner join
查詢
例: 查詢id為1的圖書關(guān)聯(lián)的英雄信息
b = BookInfo.objects.get(id=1)
b.heroinfo_set.all()
通過模型類查詢:
HeroInfo.objects.filter(hbook__id=1)
例: 查詢id為1的英雄關(guān)聯(lián)的圖書信息
h = HeroInfo.objects.get(id=1)
h.hbook
通過模型類查詢:
BookInfo.objects.filter(heroinfo__id=1)
hbook對(duì)應(yīng)的是一個(gè)在HeroInfo類中被關(guān)聯(lián)的模型類
heroinfo對(duì)應(yīng)的也是一個(gè)在BookInfo類中被關(guān)聯(lián)的模型類
而由于 heroinfo 屬于多類 所以heroinfo 有一個(gè)heroinfo_set 代表包含所有heroinfo對(duì)象的QuerySet
同理多對(duì)多關(guān)系中 互相都有_set
屬性 用來代表互相被關(guān)聯(lián)的模型類的對(duì)象的QuerySet集合
查詢HeroInfo 通過BookInfo關(guān)聯(lián)的heroinfo 實(shí)現(xiàn)inner join
例: 獲得圖書信息,通過英雄描述
BookInfo.objects.filter(heroinfo__hcomment="降龍十八掌")
查詢Bookinfo 通過Heroinfo關(guān)聯(lián)的hbook 實(shí)現(xiàn)inner join
例: 獲得英雄信息,通過圖書標(biāo)題
HeroInfo.objects.filter(hbook__btitle="天龍八部")
自關(guān)聯(lián)
自關(guān)聯(lián)的本質(zhì)是一種特殊的一對(duì)多關(guān)系
省--市--縣
省對(duì)于市屬于一對(duì)多關(guān)系
市對(duì)于縣屬于一對(duì)多關(guān)系
設(shè)置類屬性外鍵關(guān)聯(lián)自身主鍵完成自關(guān)聯(lián)
關(guān)聯(lián)屬性 = ForignKey("self", on_delete=models.CASCADE)
輸入"self"
代表自身對(duì)象 也可以輸入自身模型類名
class AreaInfo(models.Molde):
id = AutoField(primary_key=True)
name = CharField(max_length=20)
parent = ForignKey("self", null=True, blank=True, on_delete=models.CASCADE)
物理上的一張表 邏輯上的三張表
省對(duì)象 市對(duì)象 縣對(duì)象的 areainfo_set 和 parent 代表的內(nèi)容不同
管理器
Django默認(rèn)會(huì)為每個(gè)模型類生成一個(gè)objects管理器
對(duì)象
通過管理器可以實(shí)現(xiàn)對(duì)模型類對(duì)應(yīng)數(shù)據(jù)表的查詢
objects是models.Manger
類的一個(gè)對(duì)象
手動(dòng)定義管理器后Django不再自動(dòng)生成模型類的管理器對(duì)象
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
objects = models.Manage() # 定義后 Django 將不再自動(dòng)生成objects
此objects 非 自動(dòng)生成的objects 可以隨意改變管理器對(duì)象的變量名
自定義管理器類
1.創(chuàng)建一個(gè)管理器類繼承models.Manage
類
2.在模型類中通過新管理器類
創(chuàng)建一個(gè)管理器對(duì)象
重寫管理器類的應(yīng)用場(chǎng)景:
1.改變查詢集結(jié)果
# 重寫管理器類
class BookInfoManage(models.Manager):
def all(self): # 重寫all()方法
res = super(BookInfoManage, self).all() # 調(diào)用父類方法實(shí)現(xiàn)
res = res.filter(isDelete=0) # res是一個(gè)QuerySet 可以繼續(xù)使用過濾器
return res # 將改變后的結(jié)果return
# 通過自定義管理器類創(chuàng)建新的管理器對(duì)象
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
isDelete = models.BooleanField(default=False)
objects = BookInfoManage() # 此objects 非自動(dòng)創(chuàng)建的管理器
然后再通過BookInfo.objects
查詢到的結(jié)果就是修改后返回的查詢集了
2.添加額外方法
1.通過在模型類中使用類方法來得到的引用
2.通過模型類的引用創(chuàng)建實(shí)例對(duì)象
3.操作實(shí)例對(duì)象返回結(jié)果
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
isDelete = models.BooleanField(default=False)
@classmethod
def create_book(cls, btitle, isDelete)
obj = cls()
obj.btitle = btitle
obj.isDelete = isDelete
obj.save()
return obj
# 使用額外方法
book = BookInfo.create_book("甄嬛傳", True)
為了明確關(guān)系通常把這些方法定義在管理器類里
每個(gè)管理器對(duì)象都有self.model
屬性用來獲取管理器類對(duì)應(yīng)的模型類名(因?yàn)槟P皖愓{(diào)用了自定義的管理器類)
class BookInfoManage(models.Manager):
def create_book(self, btitle)
model_class = self.model # self.model是管理器對(duì)應(yīng)的模型類的引用
book = model_class() # 創(chuàng)建一個(gè)模型類對(duì)象
book.btitle = btitle
book.save()
return book
# 通過自定義管理器類創(chuàng)建新的管理器對(duì)象
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
isDelete = models.BooleanField(default=False)
objects = BookInfoManage() # 此objects 非自動(dòng)創(chuàng)建的管理器
# 使用額外方法
BookInfo.objects.create_book("甄嬛傳")
管理器的create方法
models.Manage提供的create方法通過關(guān)鍵字參數(shù)的方式創(chuàng)建一條表記錄而不需要先創(chuàng)建模型類對(duì)象
book = BookInfo.objects.create(btitle="甄嬛傳", bpub_date="1990-1-1")
返回一個(gè)模型類對(duì)象 對(duì)應(yīng)這條添加的數(shù)據(jù)表記錄
元選項(xiàng)
Django默認(rèn)生成的表名
應(yīng)用名小寫_模型類名小寫
注意
Django程序默認(rèn)通過應(yīng)用名小寫_模型類名小寫
指向要操作的數(shù)據(jù)表
如果應(yīng)用名發(fā)生改變
Django將無法通過應(yīng)用名
找到對(duì)應(yīng)的數(shù)據(jù)表因?yàn)閿?shù)據(jù)表已經(jīng)遷移完成
通過Meta指定表名后模型類調(diào)用數(shù)據(jù)表時(shí)將不再依賴于應(yīng)用名而是通過db_table
的值
元選項(xiàng)
在模型類中定義元類
修改元類的db_table
類屬性實(shí)現(xiàn)指定表名
class BookInfo(models.Model):
btitle = models.CharField(max_length=20)
isDelete = models.BooleanField(default=False)
class Meta:
db_table = "bookinfo" # 修改元類的類屬性修改表名