Django08-1:模型层(ORM)--聚合查询/分组查询/F与Q查询/开启事务/常用字段及参数/自定义字段/数据库查询优化
聚合查詢
單獨(dú)使用時(shí),用aggregate
1.只要是跟數(shù)據(jù)庫(kù)相關(guān)的模塊
????? 基本都在django.db.models里面
?????? 如果沒有應(yīng)該在django.db里面
2. 聚合查詢通常配合分組使用
from django.db.models import Avg, Sum, Max, Min, Count# 1.所有書的平均價(jià)格 res=models.Book.objects.aggregate('price')ret = models.Book.objects.all().aggregate(price_avg=Avg("price"), price_max=Max("price"), price_min=Min("price"))?
分組查詢
annotate
models后面點(diǎn)什么,就是什么分組
# 1.查詢每一本書的作者個(gè)數(shù) ret = models.Book.objects.all().annotate(author_num=Count("author")).values('title','author_num') print(ret)#author_num 自定義字段,用來統(tǒng)計(jì)每本書個(gè)數(shù)。#等價(jià) ret = models.Book.objects.all().annotate(author_num=Count("author__pk")).values('title','author_num') print(ret)只要結(jié)果是queryset對(duì)象,就可以繼續(xù).filter()和.values()
#2.統(tǒng)計(jì)每個(gè)出版社的最便宜書的價(jià)格 res=models.Publish.objects.annote(min_price=Min('book__price')).values('name','min_price')#3. 統(tǒng)計(jì)不止一個(gè)作者的圖書#a.先分組書籍,求每一步書籍的作者個(gè)數(shù)#b. 過濾不止一個(gè)作者的書籍 res=models.Book.objects.annote(author_num=Count('authors')).filter(author_num__gt=1).value('title','author_num') #4. 查詢每個(gè)作者出的書的總價(jià)格 res=models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')擴(kuò)展,其他分組方式
models.Book.values('price').annotate()分組報(bào)錯(cuò)情況:去掉嚴(yán)格模式
?
F與Q查詢
F功能:直接獲取表中某個(gè)字段對(duì)應(yīng)的數(shù)據(jù)
操作字符時(shí),F不能直接做到字符拼接,
否則變成空白
# 1.查詢賣出數(shù)大于庫(kù)存書的書籍# F查詢 from django.db.models import Fres=models.Book.objects.filter(maichu__gt=F('kuncun'))# 2.將所有書的價(jià)格提升50 models.Book.objects.update(price=F('price')+50)# 3.將所有書的名字后面加“爆款”兩個(gè)字 #***操作字符時(shí),F不能直接做到字符拼接 #***否則變成空白#需要導(dǎo)入兩個(gè)模塊 from django.db.models.functions import Concat from django.db.models import Valuemodels.Book.objects.update(title=Concat(F('tittle'),Value('爆款')))Q功能:能改變多個(gè)查詢條件的關(guān)系,與或非
# Q 查詢# 1.查詢賣出數(shù)大于100 或者價(jià)格小于600的書籍res= models.Books.objects.filter(maichu__gt=100,price__lt=600) #錯(cuò)誤,filter內(nèi)是and關(guān)系from django.db.models import Qres= models.Books.objects.filter(Q(maichu__gt=100),Q(price__lt=600)) #還是and關(guān)系res= models.Books.objects.filter(Q(maichu__gt=100)|Q(price__lt=600)) #Q可以用 |res= models.Books.objects.filter(~Q(maichu__gt=100)|Q(price__lt=600)) #前面取反# Q高階用法 能夠?qū)⒉樵儣l件左邊變成字符串形式q=Q() q.connector='or' #**修改關(guān)系 q.children.append('maichu__gt',180) q.children.append('price__lt',600)res= models.Books.objects.filter(q) #filter 也支持直接放q對(duì)象,默認(rèn)還是and關(guān)系?
開啟事務(wù)
事務(wù)ACID
事務(wù)回滾
事務(wù)確認(rèn)
?
from django.db import transactiontry:with transaction.atomic(): #開始事務(wù)操作# 先創(chuàng)建一個(gè)出版社new_publisher = models.Publisher.objects.create(name="火星出版社")# 創(chuàng)建一本書models.Book.objects.create(title="橘子物語",price=11.11,kucun=10,maichu=10,publisher_id=1000 # 指定一個(gè)不存在的出版社id)except Exception as e:print(str(e))?
orm中常用字段及參數(shù)
AutoField int自增列,必須填入?yún)?shù) primary_key=True。當(dāng)model中如果沒有自增列,則自動(dòng)會(huì)創(chuàng)建一個(gè)列名為id的列。CharField (sql:varchar) 字符類型,必須提供max_length參數(shù), max_length表示字符長(zhǎng)度。#****所有字段都有verbose_name 字段注釋*****IntegerField 一個(gè)整數(shù)類型,范圍在 -2147483648 to 2147483647。BigIntegerFieldDecimalField(Field)- 10進(jìn)制小數(shù)- 參數(shù):max_digits,小數(shù)總長(zhǎng)度decimal_places,小數(shù)位長(zhǎng)度EmailField(CharField): varchar(254)- 字符串類型,Django Admin以及ModelForm中提供驗(yàn)證機(jī)制DateField 日期字段,日期格式 YYYY-MM-DD,相當(dāng)于Python中的datetime.date()實(shí)例。DateTimeField 日期時(shí)間字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相當(dāng)于Python中的datetime.datetime()實(shí)例。auto_now:每次操作數(shù)據(jù)的時(shí)候,該字段會(huì)自動(dòng)將當(dāng)前時(shí)間更新auto_now_add:創(chuàng)建數(shù)據(jù)的時(shí)候會(huì)自動(dòng)將當(dāng)前時(shí)間記錄下來,之后只要不是人為修改,那么一直不變BooleanField(Field)- 布爾值類型數(shù)據(jù)庫(kù)存0、1TextField(Field)- 文本類型沒有字?jǐn)?shù)限制FileField(Field) -字符- 字符串,路徑保存在數(shù)據(jù)庫(kù),文件上傳到指定目錄- 參數(shù):upload_to = "" 上傳文件的保存路徑storage = None 存儲(chǔ)組件,默django.core.files.storage.FileSystemStorage例如:upload_to = "/data" 會(huì)自動(dòng)將文件保存/data目錄下,然后將文件路徑保存到數(shù)據(jù)庫(kù) ###外鍵字段 #django版本不同,級(jí)聯(lián)可能需要手動(dòng)設(shè)置自定義字段
首先參考常用的字段
# 自定義char類型class MyCharField(models.Field):"""自定義的char類型的字段類"""def __init__(self, max_length, *args, **kwargs): # max_length指定字符串寬度self.max_length = max_lengthsuper(MyCharField, self).__init__(max_length=max_length, *args, **kwargs)def db_type(self, connection):"""限定生成數(shù)據(jù)庫(kù)表的字段類型為char,長(zhǎng)度為max_length指定的值"""return 'char(%s)' % self.max_length # 返回 'char(32)' 在數(shù)據(jù)庫(kù)中就是char類型寬度32 # char類型字段的使用 class Class(models.Model):id = models.AutoField(primary_key=True)title = models.CharField(max_length=25)# 使用自定義的char類型的字段cname = MyCharField(max_length=25)?
數(shù)據(jù)庫(kù)查詢優(yōu)化
ORM語句的特點(diǎn)
惰性查詢:只寫orm語句,沒有使用,orm不會(huì)查詢數(shù)據(jù)庫(kù)。
?
defer 和 only
res=models.Book.objects.all() print(res) # 要用數(shù)據(jù)庫(kù)才查找數(shù)據(jù)庫(kù)#獲取書籍表中所有的書的名字 res=models.Book.objects.values('title')##only #獲取對(duì)象,只有title,沒有其他字段。 res=models.Book.objects.only('title')for i in res:print(i.title) #only 括號(hào)內(nèi)的字段,不會(huì)走數(shù)據(jù)庫(kù)print(i.price) #only 括號(hào)外的字段,重新走數(shù)據(jù)庫(kù) all()不需要走數(shù)據(jù)庫(kù)#defer res=models.Book.objects.defer('title') for i in res:print(i.price) #defer與only 剛好相反。括號(hào)內(nèi)走數(shù)據(jù)庫(kù),括號(hào)外不需要找數(shù)據(jù)庫(kù)。?
select_related 與prefetch_related
與跨表操作有關(guān)
res=models.Book.objects.all() for i in res:print(i.publish.name) #每循環(huán)一次就走一次數(shù)據(jù)庫(kù)res=models.Book.objects.select_related('publish') #inner join #select_related內(nèi)部直接將book與pulish連接起來,然后一次性將大表里的所有數(shù)據(jù) #全部封裝給查詢出來的對(duì)象 # 這時(shí)候無論.book表數(shù)據(jù)還是publish數(shù)據(jù)都無需要走數(shù)據(jù)查詢# select_related括號(hào)內(nèi)只能放外鍵字段 一對(duì)多,一對(duì)一 #多對(duì)多不行for i in res:print(i.publish.name)#連多表select_related('a__b__c')###prefetch_relatedres=models.Book.objects.prefetch_related('publish')# prefetch_related 實(shí)際是子查詢 # 子查詢的結(jié)果分裝到對(duì)象中 # 用戶感覺不出多一個(gè)命令for i in res:print(i.publish.name)#聯(lián)表查詢,遇到大表,效率就慢。?
?
?
?
?
?
?
總結(jié)
以上是生活随笔為你收集整理的Django08-1:模型层(ORM)--聚合查询/分组查询/F与Q查询/开启事务/常用字段及参数/自定义字段/数据库查询优化的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Django08:模型层(ORM)--测
- 下一篇: 搜狐视频Redis私有云cacheclo