#應用上面自定義的char類型 class Class(models.Model): id=models.AutoField(primary_key=True) title=models.CharField(max_length=32) class_name=RealCharField(max_length=16) gender_choice=((1,'男'),(2,'女'),(3,'保密')) gender=models.SmallIntegerField(choices=gender_choice,default=3)
AutoField(Field) - int自增列,必須填入參數 primary_key=True BigAutoField(AutoField) - bigint自增列,必須填入參數 primary_key=True 注:當model中若是沒有自增列,則自動會建立一個列名爲id的列 from django.db import models class UserInfo(models.Model): # 自動建立一個列名爲id的且爲自增的整數列 username = models.CharField(max_length=32) class Group(models.Model): # 自定義自增列 nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) SmallIntegerField(IntegerField): - 小整數 -32768 ~ 32767 PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正小整數 0 ~ 32767 IntegerField(Field) - 整數列(有符號的) -2147483648 ~ 2147483647 PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) - 正整數 0 ~ 2147483647 BigIntegerField(IntegerField): - 長整型(有符號的) -9223372036854775808 ~ 9223372036854775807 BooleanField(Field) - 布爾值類型 NullBooleanField(Field): - 能夠爲空的布爾值 CharField(Field) - 字符類型 - 必須提供max_length參數, max_length表示字符長度 TextField(Field) - 文本類型 EmailField(CharField): - 字符串類型,Django Admin以及ModelForm中提供驗證機制 IPAddressField(Field) - 字符串類型,Django Admin以及ModelForm中提供驗證 IPV4 機制 GenericIPAddressField(Field) - 字符串類型,Django Admin以及ModelForm中提供驗證 Ipv4和Ipv6 - 參數: protocol,用於指定Ipv4或Ipv6, 'both',"ipv4","ipv6" unpack_ipv4, 若是指定爲True,則輸入::ffff:192.0.2.1時候,可解析爲192.0.2.1,開啓此功能,須要protocol="both" URLField(CharField) - 字符串類型,Django Admin以及ModelForm中提供驗證 URL SlugField(CharField) - 字符串類型,Django Admin以及ModelForm中提供驗證支持 字母、數字、下劃線、鏈接符(減號) CommaSeparatedIntegerField(CharField) - 字符串類型,格式必須爲逗號分割的數字 UUIDField(Field) - 字符串類型,Django Admin以及ModelForm中提供對UUID格式的驗證 FilePathField(Field) - 字符串,Django Admin以及ModelForm中提供讀取文件夾下文件的功能 - 參數: path, 文件夾路徑 match=None, 正則匹配 recursive=False, 遞歸下面的文件夾 allow_files=True, 容許文件 allow_folders=False, 容許文件夾 FileField(Field) - 字符串,路徑保存在數據庫,文件上傳到指定目錄 - 參數: upload_to = "" 上傳文件的保存路徑 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage ImageField(FileField) - 字符串,路徑保存在數據庫,文件上傳到指定目錄 - 參數: upload_to = "" 上傳文件的保存路徑 storage = None 存儲組件,默認django.core.files.storage.FileSystemStorage width_field=None, 上傳圖片的高度保存的數據庫字段名(字符串) height_field=None 上傳圖片的寬度保存的數據庫字段名(字符串) DateTimeField(DateField) - 日期+時間格式 YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] DateField(DateTimeCheckMixin, Field) - 日期格式 YYYY-MM-DD TimeField(DateTimeCheckMixin, Field) - 時間格式 HH:MM[:ss[.uuuuuu]] DurationField(Field) - 長整數,時間間隔,數據庫中按照bigint存儲,ORM中獲取的值爲datetime.timedelta類型 FloatField(Field) - 浮點型 DecimalField(Field) - 10進制小數 - 參數: max_digits,小數總長度 decimal_places,小數位長度 BinaryField(Field) - 二進制類型
對應關係: 'AutoField': 'integer AUTO_INCREMENT', 'BigAutoField': 'bigint AUTO_INCREMENT', 'BinaryField': 'longblob', 'BooleanField': 'bool', 'CharField': 'varchar(%(max_length)s)', 'CommaSeparatedIntegerField': 'varchar(%(max_length)s)', 'DateField': 'date', 'DateTimeField': 'datetime', 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)', 'DurationField': 'bigint', 'FileField': 'varchar(%(max_length)s)', 'FilePathField': 'varchar(%(max_length)s)', 'FloatField': 'double precision', 'IntegerField': 'integer', 'BigIntegerField': 'bigint', 'IPAddressField': 'char(15)', 'GenericIPAddressField': 'char(39)', 'NullBooleanField': 'bool', 'OneToOneField': 'integer', 'PositiveIntegerField': 'integer UNSIGNED', 'PositiveSmallIntegerField': 'smallint UNSIGNED', 'SlugField': 'varchar(%(max_length)s)', 'SmallIntegerField': 'smallint', 'TextField': 'longtext', 'TimeField': 'time', 'UUIDField': 'char(32)',
models.DO_NOTHING
刪除關聯數據,引起錯誤IntegrityError
models.PROTECT
刪除關聯數據,引起錯誤ProtectedError
models.SET_NULL
刪除關聯數據,與之關聯的值設置爲null(前提FK字段須要設置爲可空)
models.SET_DEFAULT
刪除關聯數據,與之關聯的值設置爲默認值(前提FK字段須要設置默認值)
models.SET
刪除關聯數據,
a. 與之關聯的值設置爲指定值,設置:models.SET(值)
b. 與之關聯的值設置爲可執行對象的返回值,設置:models.SET(可執行對象)
示例:python
def func(): return 10 class MyModel(models.Model): user = models.ForeignKey( to="User", to_field="id", # 不寫默認關聯對方關聯表的primary_key on_delete=models.SET(func) )
#②OneToOneField
一對一字段
一般一對一字段用來擴展已有字段。(通俗的說就是一我的的全部信息不是放在一張表裏面的,簡單的信息一張表,隱私的信息另外一張表,之間經過一對一外鍵關聯)mysql
分別以圖書管理系統的Book、Publish、Author三張表直接的關係來舉例 from django.db import models class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=6, decimal_places=1) publish = models.ForeignKey(to='Publish') author = models.ManyToManyField(to='Author') class Publish(models.Model): name = models.CharField(max_length=32) email = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField(default=18)
manage.py文件複製的代碼: import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "created_by_pycharm.settings") 添加的代碼:(在main下面) import django django.setup() from app01 import models # 注意這句話必須在這裏,不能放最上面
from django.db import models # Create your models here. # 單表查詢示例表 class User(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() register_time = models.DateField(auto_now_add=True)
項目settings裏面將MySQL數據庫連入: DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'orm_test', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'root', 'PASSWORD': '123', } } 同時不要忘了在項目程序文件夾中init文件添加代碼: import pymysql pymysql.install_as_MySQLdb() 這樣才表明數據庫已經和Django項目對接完畢
固然新建完要生效,須要進行數據庫遷移(同步)操做
python3 manage.py makemigrations
python3 manage.py migrate
# 基於create建立 models.User.objects.create(name='sgt', age=18) # 基於對象的綁定方法建立 user_obj = models.User(name='王大錘', age=12) user_obj.save()
# 基於QuerySet models.User.objects.filter(name='ttt').update(age=100) # 基於對象 user_obj = models.User.objects.filter(name='sss').first() user_obj.age = 99 user_obj.save()
# 基於QuerySet models.User.objects.filter(name='ggg').delete() # 基於對象 user_obj = models.User.objects.filter(name='ttt').first() user_obj.delete()
<1> all(): 查詢全部的結果,返回QuerySet對象們的列表
git
res = models.User.objects.all() print(res) <QuerySet [<User: User object>, <User: User object>, <User: User object>, <User: User object>]>
<2> filter(**kwargs): 經過括號中的條件查詢到匹配的對象,返回QuerySet對象們的列表sql
res = models.User.objects.filter(name='sgt') print(res) <QuerySet [<User: User object>, <User: User object>, <User: User object>]> 這裏提一下:filter篩選條件是能夠有多個的,多個條件是與關係,必須所有知足纔會獲得查詢結果
<3> get(**kwargs): 返回與所給篩選條件匹配的object對象,且返回結果只有一個,若是符合篩選條件的對象超過一個或者沒有都會拋出錯誤。
數據庫
res1 = models.User.objects.get(name='sgt') # app01.models.MultipleObjectsReturned: get() returned more than one User -- it returned 3! res2 = models.User.objects.get(name='孫悟空') # app01.models.DoesNotExist: User matching query does not exist. res3 = models.User.objects.get(name='王大錘') # User object
<4> exclude(**kwargs): 返回篩選條件不匹配的QuerySet對象們的列表(取反篩選)
django
res1 = models.User.objects.exclude(name='sgt') <QuerySet [<User: User object>, <User: User object>, <User: User object>]>
<5> order_by(*field): 對查詢結果經過某一字段進行排序(默認升序),返回QuerySet對象們的列表json
res1 = models.User.objects.filter(name='sgt').order_by('age') # 排序默認是升序,若是這裏的age前加上一個負號‘-’,怎會進行降序排序。 # res1 = models.User.objects.filter(name='sgt').order_by('-age') print(res1) # <QuerySet [<User: User object>, <User: User object>, <User: User object>]> # 爲了讓結果更清晰,遍歷下獲得排好序的QuerySet對象們列表,以其age顯示順序 users = [] for user_obj in res1: users.append(user_obj.age) print(users) # [18, 22, 32]
<6> reverse(): 對查詢的排序結果進行反向排列,記住,不是反向排序,而是反向排列,返回QuerySet對象們的列表
app
res1 = models.User.objects.filter(name='sgt').order_by('age').reverse() users = [] for user_obj in res1: users.append(user_obj.age) print(users) # 結果反過來排列了:[32, 22, 18]
<7> count(): QuerySet方法,返回查詢到的QuerySet對象的數量,該方法只能對返回的查詢結果爲QuerySet對象使用,若是返回的對象是一個普通的對象,那麼結果跟res3同樣ide
res1 = models.User.objects.filter(name='sgt').count() print(res1) # 3 res2 = models.User.objects.filter(name='hahaha').count() print(res2) # 0 res3 = models.User.objects.get(name='王大錘').count() # 拋出錯誤:AttributeError: 'User' object has no attribute 'count'
<8> first(): 返回查詢結果的第一個對象,返回一個普通對象(User object)函數
res = models.User.objects.filter(name='sgt').first() print(res) # User object
<9> last(): 返回查詢結果的最後一個對象,返回一個普通對象(User object)
res = models.User.objects.filter(name='sgt').last() print(res) # User object
<10> exists(): QuerySet方法, 若是QuerySet包含數據,就返回True,不然返回False
res = models.User.objects.filter(name='sgt').exists() print(res) # True res = models.User.objects.filter(name='sgg').exists() print(res) # False
<11> values(*field): 返回一個特殊的QuerySet對象,對象裏面是一個列表套字典(model的實例化對象,而是一個可迭代的字典序列)
res = models.User.objects.filter(name='sgt').values('age') print(res) print(res.order_by('age')) print(res.order_by('age').reverse()) print(res.count()) print(res[0]) print(res.first(), res.last()) <QuerySet [{'age': 18}, {'age': 32}, {'age': 22}]> # values方法返回結果 <QuerySet [{'age': 18}, {'age': 32}, {'age': 22}]> # 經過age來反向排列,無效,說明該方法只能用在order_by以後,才能進行反向排列 <QuerySet [{'age': 18}, {'age': 22}, {'age': 32}]> # order_by <QuerySet [{'age': 32}, {'age': 22}, {'age': 18}]> # order_by後再reverse 3 # 使用count方法 {'age': 18} # 能夠用索引取出對應索引的字典 {'age': 18} {'age': 22} # 使用first和last方法
<12> values_list(*field): 它與values()很是類似,它返回的是一個元組序列的QuerySet對象
res = models.User.objects.filter(name='sgt').values_list('age') print(res) print(res.order_by('age')) print(res.order_by('age').reverse()) print(res.count()) print(res[0]) print(res.first(), res.last()) <QuerySet [(18,), (32,), (22,)]> <QuerySet [(18,), (22,), (32,)]> <QuerySet [(32,), (22,), (18,)]> 3 (18,) (18,) (22,) 結果和values方法差很少,只是把字典序列變成了元祖序列
<13> distinct(): 從返回結果中剔除重複紀錄,注意必須是全部數據都相同才知足去重條件,可是一個表中的每一條數據是不會徹底重複的,由於有primary_key的存在,就不會徹底相同,因此此方法的主要是在上面的values和values_list方法的基礎上用的話會實現一些咱們想要的結果。返回特殊的QuerySet對象
res1 = models.User.objects.filter(name='sgt') res2 = models.User.objects.filter(name='sgt').distinct() print(res1) print(res2) # <QuerySet [<User: User object>, <User: User object>, <User: User object>, <User: User object>]> # <QuerySet [<User: User object>, <User: User object>, <User: User object>, <User: User object>]> # 結果數量不變,說明沒有去重的項目,主要緣由:id沒有相同的,確定沒法去重
# 咱們用values方法的基礎上使用distinct方法: res1 = models.User.objects.filter(name='sgt').values('age') res2 = res1.distinct() print(res1) print(res2) # <QuerySet [{'age': 18}, {'age': 32}, {'age': 22}, {'age': 22}]> # <QuerySet [{'age': 18}, {'age': 32}, {'age': 22}]> # 發現這樣去重的意義就出來了
# 將結果再使用values方法,更直接顯示 res1 = models.User.objects.filter(age__gt=12).values('name', 'age') print(res1) # <QuerySet [{'name': '王大錘', 'age': 18}, {'name': '王大炮', 'age': 66}, {'name': '黃飛鴻', 'age': 88}]> res2 = models.User.objects.filter(age__lt=12).values('name', 'age') print(res2) # <QuerySet [{'name': '米小圈', 'age': 8}, {'name': '鐵頭', 'age': 9}]> res3 = models.User.objects.filter(age__gte=12).values('name', 'age') print(res3) # <QuerySet [{'name': '王大錘', 'age': 18}, {'name': '佩奇', 'age': 12}, {'name': '王大炮', 'age': 66}, {'name': '黃飛鴻', 'age': 88}]> res4 = models.User.objects.filter(age__lte=12).values('name', 'age') print(res4) # <QuerySet [{'name': '米小圈', 'age': 8}, {'name': '鐵頭', 'age': 9}, {'name': '佩奇', 'age': 12}]>
res1 = models.User.objects.filter(name__contains='i').values('name', 'age') print(res1) # <QuerySet [{'name': 'igon', 'age': 55}, {'name': 'igoN', 'age': 66}]> res2 = models.User.objects.filter(name__contains='N').values('name', 'age') print(res2) # <QuerySet [{'name': 'igoN', 'age': 66}]> res0 = models.User.objects.filter(name__icontains='j').values('name', 'age') print(res0) # <QuerySet [{'name': 'json', 'age': 11}, {'name': 'Jason', 'age': 16}]> res3 = models.User.objects.filter(name__startswith='j').values('name', 'age') print(res3) # <QuerySet [{'name': 'json', 'age': 11}]> res4 = models.User.objects.filter(name__endswith='t').values('name', 'age') print(res4) # <QuerySet [{'name': 'sgt', 'age': 18}]>
res = models.User.objects.filter(register_time__year=2018).values('name', 'age', 'register_time') print(res) # <QuerySet [{'name': 'json', 'age': 11, 'register_time': datetime.date(2018, 6, 21)}]>
在指定容器內__in=[a,b,c],在指定範圍內__range=[m,n],首尾都包括在內
res1 = models.User.objects.filter(age__in=[66, 88]).values('name', 'age') print(res1) # <QuerySet [{'name': '王大炮', 'age': 66}, {'name': '黃飛鴻', 'age': 88}, {'name': 'igoN', 'age': 66}]> res2 = models.User.objects.filter(age__range=[9, 12]).values('name', 'age') print(res2) # <QuerySet [{'name': '鐵頭', 'age': 9}, {'name': '佩奇', 'age': 12}, {'name': 'json', 'age': 11}]>
#一對一(OneToOneField):一對一字段不管建在哪張關係表裏面均可以,可是推薦建在查詢頻率比較高的那張表裏面
#一對多(ForeignKey):一對多字段建在多的那一方
#多對多(ManyToManyField):多對多字段不管建在哪張關係表裏面均可以,可是推薦建在查詢頻率比較高的那張表裏面
多對多操做:
添加add(),
修改set(),
移除remove() 注意不能接收可迭代對象,
清空clear() 無需傳參
如何判斷表與表之間究竟是什麼關係
換位思考
A能不能有多個B
B能不能有多個A
from django.db import models # 多表查詢示例表 class Book(models.Model): title = models.CharField(max_length=32) price = models.DecimalField(max_digits=8, decimal_places=2) publish_date = models.DateField(auto_now_add=True) # 外鍵關係 # 一對多:(外鍵) publish = models.ForeignKey(to='Publish') # 多對多: author = models.ManyToManyField(to='Author') # 這是一個虛擬字段, 信號字段 class Publish(models.Model): name = models.CharField(max_length=32) addr = models.CharField(max_length=32) email = models.EmailField() # 對應的就是varchar類型 class Author(models.Model): name = models.CharField(max_length=32) age = models.IntegerField() # 一對一關係 authordetail = models.OneToOneField(to='AuthorDetail') class AuthorDetail(models.Model): phone = models.CharField(max_length=32) addr = models.CharField(max_length=32)
# 一對多新增: # 因爲book表和Publish表示多對一的關係,因此咱們須要先創建Publish相關數據才能進行book記錄新增 models.Publish.objects.create(name='東方出版社', addr='北京', email='123@163.com') models.Publish.objects.create(name='西方出版社', addr='內蒙', email='456@163.com') models.Publish.objects.create(name='南方出版社', addr='武漢', email='789@163.com') models.Publish.objects.create(name='北方出版社', addr='上海', email='546@163.com')
# 新增book記錄(直接添加寫id) models.Book.objects.create(title='西遊記', price=66, publish_id=1) models.Book.objects.create(title='紅樓夢', price=266, publish_id=2) models.Book.objects.create(title='西廂記', price=166, publish_id=3) models.Book.objects.create(title='金屏梅', price=366, publish_id=4)
# 一對多新增,傳輸數據對象 publish_obj = models.Publish.objects.filter(pk=1).first() models.Book.objects.create(title='三國志', price=48, publish=publish_obj)
# 一對多修改 # QuerySet方法修改 ① models.Book.objects.filter(pk=1).update(publish_id=2) ② publish_obj = models.Publish.objects.filter(pk=4).first() models.Book.objects.filter(pk=1).update(publish=publish_obj) # 對象方法修改 ① book_obj = models.Book.objects.filter(pk=1).first() book_obj.publish_id = 3 # 點表中真實存在的字段名 book_obj.save() ② book_obj = models.Book.objects.filter(pk=1).first() publish_obj = models.Publish.objects.filter(pk=1).first() book_obj.publish = publish_obj book_obj.save()
# 多對一刪除 ①QuerySet方法 # 當刪除'多'的表數據,則那張'一'的表無影響 models.Book.objects.filter(pk=1).delete() # 當刪除'一'的表數據,則那張'多'的表對應的記錄會刪除 models.Publish.objects.filter(pk=2).delete() ②對象方法: book_obj = models.Book.objects.filter(pk=2).first() book_obj.delete()
# 多對多關係表的新增 # 過程:先新增數據,後綁定關係 # 先新增author數據和book數據(假設做者信息已經存在對應Detail表) models.Author.objects.create(name='蕭鼎', age=66, authordetail_id=1) models.Author.objects.create(name='路遙', age=56, authordetail_id=2) models.Author.objects.create(name='三毛', age=77, authordetail_id=3) models.Author.objects.create(name='金庸', age=95, authordetail_id=4) book_obj = models.Book.objects.create(title='畫江湖', price=99, publish_id=1) book_obj.author.add(2, 3) 固然新增也支持傳對象的方式 author_obj1 = models.Author.objects.filter(pk=1).first() author_obj2 = models.Author.objects.filter(pk=2).first() book_obj.author.add(author_obj1, author_obj2)
修改
# 修改book和author記錄及其關係:set()方法,必須傳可迭代對象 book_obj = models.Book.objects.filter(pk=3).first() # 修改方法和新增相似,也是修改自身數據後再修改關係 # 能夠傳數字和對象,而且也支持傳多個 # 傳id book_obj.author.set((1,)) # 傳一個 book_obj.author.set((1,2,3)) # 傳多個 # 傳對象 author_list = models.Author.objects.all() book_obj = models.Book.objects.filter(pk=3).first() book_obj.author.set(author_list)
# 多對多刪除 # QuerySet方法 models.Book.objects.filter(pk=4).delete() # 刪除id爲4的書,同時會自動刪除此書與做者之間的關係,此時綁定關係會自動刪除 # 對象方法 book_obj = models.Book.objects.filter(pk=5).first() book_obj.author.remove(2) # 先刪除關係不會刪除book記錄數據 book_obj = models.Book.objects.filter(pk=6).first() book_obj.delete() # 刪除book對象,會自動觸發刪除綁定關係 # 假設一本書有多個做者 book_obj = models.Book.objects.filter(pk=1).first() author_list = models.Author.objects.all() book_obj.author.remove(*author_list) # 注意這裏的QuerySet須要打散才行
# 一對一,author表建立外鍵綁定關係到authordetail表,刪除建立外鍵的那張author表的記錄,另外一方無影響 models.Author.objects.filter(pk=1).delete() # 一對一,刪除非外鍵的那張authordetail表記錄,則綁定關係以及對應的author表記錄都會隨之刪除 models.AuthorDetail.objects.filter(pk=2).delete()
# 一對一新增:建立外鍵的表author中新增記錄,對應的外鍵必須未用佔且存在,由於是一對一關係,不然報錯 models.Author.objects.create(name='王錘', age=88, authordetail_id=1) # 一對一新增,authordetail表中新增記錄,author表無影響. models.AuthorDetail.objects.create(phone='123', addr='毛里求斯')
# 一對一修改, models.Author.objects.filter(pk=8).update(name='湯匙') models.AuthorDetail.objects.filter(pk=4).update(addr='伊拉克') # 一對一修改 關聯外鍵值: # 外鍵值必須未佔用,且存在,否則報錯 models.Author.objects.filter(pk=8).update(authordetail_id=5)
book_obj = models.Book.objects.filter(pk=3).first() book_obj.authors.clear() # 清空當前書籍對應的全部做者的綁定關係
正向查詢:經過一張表a查詢另外一張表b,若是a與b之間的關係外鍵是建在a中,那麼咱們從a中能經過這個外鍵字段查詢到b表中的對應數據的過程就叫作正向查詢
反向查詢:上面的正向查詢,若是從b表去找a表的數據,外鍵仍是建在a表中,這時候b表中就沒有與a表關聯的字段,此時b查到a就須要用另外的手段來實現,這種就叫反向查詢
正向、反向查詢方法:
原則:正向查詢按字段,反向查詢按表名小寫
# 一對一
Author表和AuthorDetail表是一對一關係:(外鍵在Author表中)
## 正向查詢:從Author查到AuthorDetail: res = models.Author.objects.filter(pk=3).first().authordetail.addr print(res) # 冥王星 ## 反向查詢:從AuthorDetail 查到Author res1 = models.AuthorDetail.objects.filter(pk=3).first().author.name print(res1) # 三毛
# 一對多
# Book到Publish res = models.Book.objects.filter(pk=1).first().publish.name print(res) # 東方出版社 # Publish到Book res1 = models.Publish.objects.filter(pk=2).first().book_set.all() print(res1) # <QuerySet [<Book: Book object>, <Book: Book object>]> res2 = models.Publish.objects.filter(pk=2).first().book_set.all().values('title') print(res2) # <QuerySet [{'title': '紅樓夢'}, {'title': '西遊記'}]>
# 多對多
# 正向查詢 res1 = models.Book.objects.filter(pk=2).first().author.all() print(res1) # <QuerySet [<Author: Author object>, <Author: Author object>]> res2 = models.Book.objects.filter(pk=2).first().author.all().values('name') print(res2) # <QuerySet [{'name': '金庸'}, {'name': '湯匙'}]> # 反向查詢 res3 = models.Author.objects.filter(pk=3).first().book_set.all() print(res3) # <QuerySet [<Book: Book object>, <Book: Book object>]> res4 = models.Author.objects.filter(pk=3).first().book_set.all().values('title') print(res4) # <QuerySet [{'title': '西廂記'}, {'title': '紅樓夢'}]>
規律:一對多、多對多 反向查詢的時候要加_set.all()
一對一 反向查詢不用加
res = models.Book.objects.filter(title='紅樓夢').values('publish__name') print(res) # <QuerySet [{'publish__name': '南方出版社'}]>
② 查詢書籍爲西遊記的做者的姓名:
res = models.Book.objects.filter(title='西遊記').values('author__name') print(res) # <QuerySet [{'author__name': '三毛'}, {'author__name': '唐唐'}]>
③ 查詢南方出版社第一版的書名:
res = models.Publish.objects.filter(name='南方出版社').values('book__title') print(res) # <QuerySet [{'book__title': '紅樓夢'}, {'book__title': '西遊記'}]>
④ 查詢電話號碼是911的做者寫的書名:
res = models.AuthorDetail.objects.filter(phone='911').values('author__book__title') print(res) # <QuerySet [{'author__book__title': '三國志'}, {'author__book__title': '西廂記'}]>
⑤ 查詢做者名字爲金庸寫的書的書名:
res = models.Author.objects.filter(name='金庸').values('book__title') print(res) # <QuerySet [{'book__title': '三國志'}, {'book__title': '西廂記'}]>
⑥ 查詢書籍爲西遊記的做者的電話號碼:
res = models.Book.objects.filter(title='西遊記').values('author__name', 'author__authordetail__phone') print(res) # <QuerySet [{'author__name': '三毛', 'author__authordetail__phone': '119'}, # {'author__name': '唐唐', 'author__authordetail__phone': '110'}]>
⑦ 經過做者細節表 查詢做者叫金庸的電話號碼
res = models.AuthorDetail.objects.filter(author__name='金庸').values('phone') print(res) # <QuerySet [{'phone': '911'}]>
⑧ 從書這張表 查詢出版社爲南方出版社的全部圖書的名字和價格
res = models.Book.objects.filter(publish__name='南方出版社').values('title', 'price') print(res) # <QuerySet [{'title': '紅樓夢', 'price': Decimal('67.00')}, {'title': '西遊記', 'price': Decimal('87.00')}]>
⑨ 查詢東方出版社第一版的書的價格大於45的書
res = models.Publish.objects.filter(name='東方出版社', book__price__gt=45).values('book__title', 'book__price') print(res) # <QuerySet [{'book__title': '三國志', 'book__price': Decimal('48.00')}]>
from django.db.models import Avg, Sum, Max, Min, Count
示例:
from django.db.models import Avg,Sum,Max,Min,Count、 查詢全部書籍的平均價格,最大價格,書的數量 res = models.Book.objects.all().aggregate(Avg('price'), Max('price'), Count('title')) print(res) # {'price__avg': 56.6, 'price__max': Decimal('87.00'), 'title__count': 5}
能夠給聚合值指定一個名稱,用於使用該聚合值
若是你想要爲聚合值指定一個名稱,能夠向聚合子句提供它。 >>> models.Book.objects.aggregate(average_price=Avg('price')) {'average_price': 13.233333}
res = models.Publish.objects.annotate(avg_price=Avg('book__price')).values('name', 'avg_price') print(res) # <QuerySet [{'name': '東方出版社', 'avg_price': 46.0}, {'name': '南方出版社', 'avg_price': 77.0}, {'name': '北方出版社', 'avg_price': 37.0}]>
統計出每一個出版社買的最便宜的書的價格
# <QuerySet [{'name': '東方出版社', 'avg_price': 46.0}, {'name': '南方出版社', 'avg_price': 77.0}, {'name': '北方出版社', 'avg_price': 37.0}]> res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price' ) print(res) # <QuerySet [{'name': '東方出版社', 'min_price': Decimal('44.00')}, {'name': '南方出版社', 'min_price': Decimal('67.00')}, {'name': '北方出版社', 'min_price': Decimal('37.00')}]>
統計不止一個做者的圖書
res = models.Book.objects.annotate(author_num=Count('author')).filter(author_num__gt=1).values('title') print(res) # <QuerySet [{'title': '西廂記'}]>