?ORM 查詢的數據類型:
QuerySet與惰性機制(可以看作是一個列表)
所謂惰性機制:表名.objects.all()或者.filter()等都只是返回了一個QuerySet(查詢結果集對象),它并不會馬上執行sql,而是當調用QuerySet的時候才執行。
QuerySet特點:
? ? ?? <1>? 可迭代的?
? ? ?? <2>? 可切片
? ? ? ?<3>? 惰性計算和緩存機制
例:
info=models.table_name.objects.all()[0:5] #切片 info= models.table_name.objects.all()[3] #索引 info= models.table_name.objects.all() #可迭代 print(info.title) for obj in info: print(obj.title)
?
?類對象
<class 'models.表名'>類對象
獲取字段數值為? 類.字段名?
?
?
創建 models 數據庫
一對一表創建
class A1(models.Model):id = models.IntegerField(primary_key=True)A11 = models.CharField(max_length=20)A12 = models.CharField(max_length=20)A13 = models.CharField(max_length=20)class E1(models.Model):id = models.IntegerField(primary_key=True)E11 = models.OneToOneField('A1',to_field='id',on_delete=models.CASCADE)E12 = models.CharField(max_length=20)# 定義 一對一關聯: # 格式: # 字段 = models.OneToOneFied('關聯表',to_field='關聯表字段',on_delete=models.CASCADE)# 可添加參數:# related_name=名字 #外鍵反向查找別名(方便反向查找)# 使用方式; obj.名字.all()#在寫ForeignKey字段的時候,如果想要在反向查找時不使用默認的 小寫的表名_set,就在定義這個字段的時間加related參數!# related_query_name 字段=別名# 使用方式; obj.別名.all()# 一張表內兩個外鍵 需要添加 related_query_name= 名字 從而識別是哪個外鍵值 # 示例: # B11 = models.ForeignKey('A1',to_field='id',on_delete=models.CASCADE)
?
外鍵(一對多創建)
# B1表跟A1表形成外鍵關系 class A1(models.Model):id = models.IntegerField(primary_key=True)A11 = models.CharField(max_length=20)A12 = models.CharField(max_length=20)A13 = models.CharField(max_length=20)class B1(models.Model):id = models.IntegerField(primary_key=True)B11 = models.ForeignKey('A1',to_field='id',on_delete=models.CASCADE)B12 = models.CharField(max_length=20)B13 = models.CharField(max_length=20)# 定義 外鍵: # 格式: # 字段 = models.ForeignKey('關聯表',to_field='關聯表字段',on_delete=models.CASCADE)# 可添加參數:# related_name=名字 #外鍵反向查找別名(方便反向查找)# 使用方式; obj.名字.all()#在寫ForeignKey字段的時候,如果想要在反向查找時不使用默認的 小寫的表名_set,就在定義這個字段的時間加related參數!# related_query_name 字段=別名# 使用方式; obj.別名.all()# 一張表內兩個外鍵 需要添加 related_query_name= 名字 從而識別是哪個外鍵值 # 示例: # B11 = models.ForeignKey('A1',to_field='id',on_delete=models.CASCADE)
?
多對多表創建
# C1表跟D1表形成多對多的關系 class C1 (models.Model):id = models.IntegerField(primary_key=True)m = models.ManyToManyField('D1')C12 = models.CharField(max_length=20)C13 = models.CharField(max_length=20)class D1 (models.Model):id = models.IntegerField(primary_key=True)D12 = models.CharField(max_length=20)D13 = models.CharField(max_length=20)# 定義 多對多: # 格式: # 字段 = models.ForeignKey('關聯表',to_field='關聯表字段',on_delete=models.CASCADE)# 可添加參數:# through='UserFans'指定第3張關系表的表名# through_fields 指定第3張關系表的字段 # 示例: # m = models.ManyToManyField('D1')
?
?多對多自關聯創建
# userinfo 形成多對多的自關聯 class Userinfo(models.Model):nikename=models.CharField(max_length=32)username=models.CharField(max_length=32)password=models.CharField(max_length=64)sex=((1,'男'),(2,'女'))gender=models.IntegerField(choices=sex)m=models.ManyToManyField('Userinfo')
?
ORM 操作
單表操作/追加參數
# # 單表添加數據 # 單表操作# 格式:# 表名.objects.create() # 導入的是表# module.表名.objects.create() # 導入的是module模塊# # 添加方式一:# models.表名.objects.create(字段1='參數1', 字段2='參數2')# # 添加方式二:# obj = models.表名(字段1 = '參數1', 字段2 = '參數2')# obj.save()# 示例:# # 方式一# models.A1.objects.create(A11='A1',A12='1',A13='1')# # # 方式二# data = {'A11': 'A2', 'A12': '2', 'A13': '2'}# models.A1.objects.create(**data)# # # 方式三# data2 = {'A11': 'A3', 'A12': '3', 'A13': '3'}# obj = models.A1(**data2)# obj.save()# QuerySet 數據類型:可以看作是一個列表 # QuerySet 對象,可切片,索引,迭代# <class 'models.A1'>類對象: 就是一個類 # 相當于一個類,獲取字段數值為 類.字段名# 單表查詢數據# 查詢所有數據# 格式:# info=models.表名.objects.all()# 返回值:# query_set對象集合 [對象1、對象2、.... ]# obj = models.A1.objects.all()# print(obj) # QuerySet 對象# 查詢單條數據#方式一 filter# 格式一:# info = models.表名.objects.filter(字段=參數)# 返回值:# 取值可以為 info[0]# query_set對象集合 [對象1]# obj2 = models.A1.objects.filter(id=1) #查詢不到數據為 空 QuerySet對象# print(obj2) # QuerySet 對象# # filter 可追加參數# obj21 = models.A1.objects.filter(id=1).first() #第一條# obj22 = models.A1.objects.filter(id=1).last() #最后一條# obj23 = models.A1.objects.filter(id=1).values_list() #元組類型輸出# obj24 = models.A1.objects.filter(id=1).values() #字典類型輸出# # print(type(obj21/22/23/24)) #<class 'models.A1'>類對象# .oder_by(-id):按照某列排序# .exclude(字段):字段獲取數據時排除#方式二 get# info = models.表名.objects.get(字段=參數)# 返回值:# 單個對象,沒有找到會報錯# obj3 = models.A1.objects.get(id=1) #查詢不到數據報錯!!!!# print(obj3)# print(type(obj3)) #<class 'models.A1'>類對象# 單表刪除數據# 方式一:# models.A1.objects.filter(id=1).delete()# 方式二:# ob1 = models.A1.objects.get(id=1)# ob1.delete()# ob1.save()# 單表修改數據#修改方式1 update()# 格式:# models.表名.objects.filter(字段=參數).update(字段=參數)# models.A1.objects.filter(id=3).update(A11='A33',A12='A33',A13='A33')# data_updata = {'A11':'A33','A12':'A33','A13':'A33'}# models.A1.objects.filter(id=4).update(**data_updata)#修改方式2 obj.save()# obj = models.表名.objects.filter(字段=參數).get(字段=參數)# obj.字段 = 參數# obj.save()# ob1 = models.A1.objects.get(id=3)# ob1.A11 = 'A44'# ob1.A12 = 'A44'# ob1.A13 = 'A44'# ob1.save()# 更新數據操作:# 示例:# 格式:# models.表名.objects.update_or_create(條件1=參數1, defaults={字段:屬性})# 示例:# tk = username# models.Token.objects.update_or_create(user=user, defaults={'token': tk})# 找到更新 如果沒有找到創建defaults={} 中的數據
?
一對一表查詢
# 一對一表操作# 添加刪除修改(略)# # 查詢# 正向查詢(根據ontoon字段直接查詢)# info1 = models.E1.objects.filter(id=1).values('id','E12','E11__A12','E11__A13')# info2 = models.E1.objects.filter(id=1).first().E11# print(info1) # QuerySet# print(info2) # A1 object (3)# #反向查詢(反向查詢跟foreignkey不同時的不需要 表名_set 這里只需要對表表名即可)# info1 = models.A1.objects.filter(id=3).values('id','A12','e1__id','e1__E12')# info2 = models.A1.objects.filter(id=3).first().e1# print(info1) # QuerySet# print(info2) # E1 object (1)
?
一對多表操作
# 一對多表操作(外鍵)# # 一對多表操作:# 添加方式一:# models.表名.objects.create(字段1='參數1',字段2='參數2',外鍵ID='參數')# # 添加方式二:# obj=models.表名(字段1='參數1',字段2='參數2',外鍵=參數)# obj.save()# 一對多添加數據#方式一# data = {'B12':'B66','B13':'B66','B11_id':3}# models.B1.objects.create(**data)#方式二# data = {'B12':'B55','B13':'B55','B11_id':4}# obj = models.B1(**data)# obj.save()# 一對多表刪除數據(跟單表操作一樣)# 方式一:# models.B1.objects.filter(id=6).delete()# 方式二:# models.B1.objects.get(B12='B66').delete()# 一對多表修改數據(跟單表操作一樣)# models.B1.objects.filter(id=3).update(B11_id=4)#一對多表查詢數據(跨表查詢)# 一對多表 跨表查詢(正向查找 B表-外鍵字段-A表字段,下面兩句等效)# info = models.B1.objects.filter(id=3).first().B11# info2 = models.B1.objects.get(id=3).B11# print(info) # A1 object (4)# print(info2) # A1 object (4)# # 一對多表 跨表查詢(反向查找)(下面兩條結果一致)# #方式一(根據 類的方式查找 ) (info.小寫表名_set)# info = models.A1.objects.filter(id=4)# info1 = info.first().b1_set.values()# print(info1) #values --- QuerySet類型# #方式二(根據values方式查找)(在values中 '小寫表名__字段名' )# info2 = models.A1.objects.values('b1__B11','b1__B12','b1__B13').filter(id=4)# print(info2) #values --- QuerySet類型
?
多對多表操作
#多對多表操作#多對多表添加操作# 如果兩表之間存在雙向1對N關系,就無法使用外鍵來描述其關系了;# 只能使用多對多的方式,新增第三張表關系描述表;# add() 添加# clear() 清空# remove() 刪除某個對象# 正向添加 通過 多對多字段m.add增加#C1表id =1 字段 關聯 D1表的 id = 1,2,3# obj = models.C1.objects.filter(id=1).first()# obj.m.add(1,2,3)# 反向添加 通過 小寫表名_set.add增加# D1表id =1 字段 關聯 C1表的 id = 1,2,3# obj2 = models.D1.objects.filter(id=1).first()# obj2.c1_set.add(1,2,3)#C1 id=3 關聯 D1表id>3的數據# obj1 = models.C1.objects.filter(id=3).first()# obj2 = models.D1.objects.filter(id__gt=3)# obj1.m.add(*obj2)#多對多表刪除操作# 正向刪除# obj1 = models.C1.objects.filter(id=1).first()# obj1.m.remove(1,2,3)# 逆向刪除# obj2 = models.D1.objects.filter(id=1).first()# obj2.c1_set.remove(2,3)# 清除數據# obj3 = models.C1.objects.filter(id=3).first()# obj3.m.clear()#多對多修改# ManyToManyField()字段 自動創建第3張關系表,可以使用字段跨表查詢,但無法直接操作第3張表,# obj.m.all() 只有查詢和清空 方法#多對多查詢# 正向查詢(通過多對多字段 直接查詢)# obj = models.C1.objects.get(id=3).m.values()# print(obj)# 反向查詢(通過.表名_set 查詢)# obj = models.D1.objects.get(id=1).c1_set.values_list()# print(obj)
多對多自關聯操作
# 多對多自關聯(由原來的3張表,變成只有2張表) # 把兩張表通過 choices字段合并為一張表 # ‘第三張關系表’ 使用models.ManyToManyField('Userinfo')生成# 同表正反向查詢# 多對多 自關聯 通過男士查詢女生# boy_obj = models.Userinfo.objects.filter(id=2).first()# res = boy_obj.m.all()# for row in res:# print(row.nikename)# # 多對多自關聯 之通過女士查詢男生# girl_obj = models.Userinfo.objects.filter(id=4).first()# res = girl_obj.userinfo_set.all()# for obj in res:# print(obj.nikename)
?
查詢性能探究
# 查詢性能 :# 1、select_related:結果為對象 注意query_set類型的對象 都有該方法# 原理: 查詢時主動完成連表形成一張大表,for循環時不用額外發請求;# 試用場景: 節省硬盤空間,數據量少時候適用相當于做了一次數據庫查詢;# info = models.B1.objects.filter(B11=4).all().select_related()# for i in info:# print(i)# 2、prefetch_related:結果都對象是# 原理:雖好,但是做連表操作依然會影響查詢性能,所以出現prefetch_related# prefetch_related:不做連表,多次單表查詢外鍵表 去重之后顯示, 2次單表查詢(有幾個外鍵做幾次1+N次單表查詢,# 適用場景:效率高,數據量大的時候試用# info = models.B1.objects.filter(B11=4).all().prefetch_related()# for i in info:# print(i)
?
F查詢與Q查詢
# F查詢與Q查詢#F 可以獲取對象中的字段的屬性(列),并對其進行操作;# from django.db.models import F,Q# models.表名.objects.all().update(price=F('price')+1) #所在的列進行操作# Q多條件組合查詢# Q()可以使orm的fifter()方法支持, 多個查詢條件,使用邏輯關系(&、|、~)包含、組合到一起進行多條件查詢;# 語法:# fifter(Q(查詢條件1)| Q(查詢條件2))# fifter(Q(查詢條件2)& Q(查詢條件3))# fifter(Q(查詢條件4)& ~Q(查詢條件5))# fifter(Q(查詢條件6)| Q(Q(查詢條件4)& ~ Q(Q(查詢條件5)& Q(查詢條件3)))包含# from django.db.models import F,Q# 1、F 可以獲取對象中的字段的屬性(列),并且對其進行操作;# # models.Book.objects.all().update(price=F('price')+1)# 2、Q多條件組合查詢# #如果 多個查詢條件 涉及到邏輯使用 fifter(,隔開)可以表示與,但沒法表示或非得關系# #查詢 書名包含作者名的書# book=models.Book.objects.filter(title__icontains='偉',author__name__contains='偉').values('title')# #如何讓orm 中得 fifter 支持邏輯判斷+多條件查詢? Q()登場# book=models.Book.objects.filter(Q(title__icontains='偉') & Q(author__name__contains='偉')).values('title')# book=models.Book.objects.filter(Q(author__name__contains='偉') & ~Q(title__icontains='偉')).values('title')# # #多條件包含組合查詢# #查詢作者姓名中包含 方/少/偉/書名包含偉3字 并且出版社地址以山西開頭的書# book=models.Book.objects.filter(# Q(# Q(author__name__contains='方') |# Q(author__name__contains='少') |# Q(title__icontains='偉')|# Q(author__name__contains='偉')# )# &# Q(publish__addr__contains='山西')# ).values('title')# print(book)# 注意:Q查詢條件和非Q查詢條件混合使用注意,不包Q()的查詢條件一點要放在Q(查詢條件)后面
?
部分資料查詢于
https://www.cnblogs.com/sss4/p/7070942.html
?