聚合查詢
單獨使用時,用aggregate
1.只要是跟數據庫相關的模塊
????? 基本都在django.db.models里面
?????? 如果沒有應該在django.db里面
2. 聚合查詢通常配合分組使用
from django.db.models import Avg, Sum, Max, Min, Count# 1.所有書的平均價格
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后面點什么,就是什么分組
# 1.查詢每一本書的作者個數
ret = models.Book.objects.all().annotate(author_num=Count("author")).values('title','author_num')
print(ret)#author_num 自定義字段,用來統計每本書個數。#等價
ret = models.Book.objects.all().annotate(author_num=Count("author__pk")).values('title','author_num')
print(ret)
只要結果是queryset對象,就可以繼續.filter()和.values()
#2.統計每個出版社的最便宜書的價格
res=models.Publish.objects.annote(min_price=Min('book__price')).values('name','min_price')#3. 統計不止一個作者的圖書#a.先分組書籍,求每一步書籍的作者個數#b. 過濾不止一個作者的書籍
res=models.Book.objects.annote(author_num=Count('authors')).filter(author_num__gt=1).value('title','author_num')
#4. 查詢每個作者出的書的總價格
res=models.Author.objects.annotate(sum_price=Sum('book__price')).values('name','sum_price')
擴展,其他分組方式
models.Book.values('price').annotate()
分組報錯情況:去掉嚴格模式
?
F與Q查詢
F功能:直接獲取表中某個字段對應的數據
操作字符時,F不能直接做到字符拼接,
否則變成空白
# 1.查詢賣出數大于庫存書的書籍# F查詢
from django.db.models import Fres=models.Book.objects.filter(maichu__gt=F('kuncun'))# 2.將所有書的價格提升50
models.Book.objects.update(price=F('price')+50)# 3.將所有書的名字后面加“爆款”兩個字
#***操作字符時,F不能直接做到字符拼接
#***否則變成空白#需要導入兩個模塊
from django.db.models.functions import Concat
from django.db.models import Valuemodels.Book.objects.update(title=Concat(F('tittle'),Value('爆款')))
Q功能:能改變多個查詢條件的關系,與或非
# Q 查詢# 1.查詢賣出數大于100 或者價格小于600的書籍res= models.Books.objects.filter(maichu__gt=100,price__lt=600)
#錯誤,filter內是and關系from django.db.models import Qres= models.Books.objects.filter(Q(maichu__gt=100),Q(price__lt=600)) #還是and關系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=Q()
q.connector='or' #**修改關系
q.children.append('maichu__gt',180)
q.children.append('price__lt',600)res= models.Books.objects.filter(q) #filter 也支持直接放q對象,默認還是and關系
?
開啟事務
事務ACID
事務回滾
事務確認
?
from django.db import transactiontry:with transaction.atomic(): #開始事務操作# 先創建一個出版社new_publisher = models.Publisher.objects.create(name="火星出版社")# 創建一本書models.Book.objects.create(title="橘子物語",price=11.11,kucun=10,maichu=10,publisher_id=1000 # 指定一個不存在的出版社id)except Exception as e:print(str(e))
?
orm中常用字段及參數
AutoField
int自增列,必須填入參數 primary_key=True。當model中如果沒有自增列,則自動會創建一個列名為id的列。CharField (sql:varchar)
字符類型,必須提供max_length參數, max_length表示字符長度。#****所有字段都有verbose_name 字段注釋*****IntegerField
一個整數類型,范圍在 -2147483648 to 2147483647。BigIntegerFieldDecimalField(Field)- 10進制小數- 參數:max_digits,小數總長度decimal_places,小數位長度EmailField(CharField): varchar(254)- 字符串類型,Django Admin以及ModelForm中提供驗證機制DateField
日期字段,日期格式 YYYY-MM-DD,相當于Python中的datetime.date()實例。DateTimeField
日期時間字段,格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ],相當于Python中的datetime.datetime()實例。auto_now:每次操作數據的時候,該字段會自動將當前時間更新auto_now_add:創建數據的時候會自動將當前時間記錄下來,之后只要不是人為修改,那么一直不變BooleanField(Field)- 布爾值類型數據庫存0、1TextField(Field)- 文本類型沒有字數限制FileField(Field) -字符- 字符串,路徑保存在數據庫,文件上傳到指定目錄- 參數:upload_to = "" 上傳文件的保存路徑storage = None 存儲組件,默django.core.files.storage.FileSystemStorage例如:upload_to = "/data" 會自動將文件保存/data目錄下,然后將文件路徑保存到數據庫 ###外鍵字段
#django版本不同,級聯可能需要手動設置
自定義字段
首先參考常用的字段
# 自定義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):"""限定生成數據庫表的字段類型為char,長度為max_length指定的值"""return 'char(%s)' % self.max_length # 返回 'char(32)' 在數據庫中就是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)
?
數據庫查詢優化
ORM語句的特點
惰性查詢:只寫orm語句,沒有使用,orm不會查詢數據庫。
?
defer 和 only
res=models.Book.objects.all()
print(res) # 要用數據庫才查找數據庫#獲取書籍表中所有的書的名字
res=models.Book.objects.values('title')##only
#獲取對象,只有title,沒有其他字段。
res=models.Book.objects.only('title')for i in res:print(i.title) #only 括號內的字段,不會走數據庫print(i.price) #only 括號外的字段,重新走數據庫 all()不需要走數據庫#defer
res=models.Book.objects.defer('title')
for i in res:print(i.price) #defer與only 剛好相反。括號內走數據庫,括號外不需要找數據庫。
?
select_related 與prefetch_related
與跨表操作有關
res=models.Book.objects.all()
for i in res:print(i.publish.name) #每循環一次就走一次數據庫res=models.Book.objects.select_related('publish') #inner join
#select_related內部直接將book與pulish連接起來,然后一次性將大表里的所有數據
#全部封裝給查詢出來的對象
# 這時候無論.book表數據還是publish數據都無需要走數據查詢# select_related括號內只能放外鍵字段 一對多,一對一
#多對多不行for i in res:print(i.publish.name)#連多表select_related('a__b__c')###prefetch_relatedres=models.Book.objects.prefetch_related('publish')# prefetch_related 實際是子查詢
# 子查詢的結果分裝到對象中
# 用戶感覺不出多一個命令for i in res:print(i.publish.name)#聯表查詢,遇到大表,效率就慢。
?
?
?
?
?
?
?