做者模型:一個做者有姓名和年齡。python
做者詳細模型:把做者的詳情放到詳情表,包含生日,手機號,家庭住址等信息。做者詳情模型和做者模型之間是一對一的關係(one-to-one)django
出版社模型:出版社有名稱,所在城市以及email。函數
書籍模型: 書籍有書名和出版日期,一本書可能會有多個做者,一個做者也能夠寫多本書,因此做者和書籍的關係就是多對多的關聯關係(many-to-many);一本書只應該由一個出版商出版,因此出版商和書籍是一對多關聯關係(one-to-many)。spa
生成表以下:code
先建立沒有外鍵的數據,而後類的字段等於對象(方式一)對象
authordetail = AuthorDetail.objects.create(phone='19856482547',email='4878779@qq.com') author = Author.objects.create(name='張三',age=28,authordetail=authordetail)
直接知道姓名給authordetail_id 賦值 (方式二)blog
author = Author.objects.create(name='安妮',age=12,authordetail_id=7) print(author)
方式一 (同上)排序
publish = Publish.objects.create(name='北京出版社',addr='北京西路',email='887@163.com') book = Book.objects.create(name='花非花',price=34,pub_date='1972-9-4',publish=publish)
方式二rem
publish = Publish.objects.filter(name='北京出版社').first() book = Book.objects.create(name='霧非霧',price=36,pub_date='1972-9-4',publish_id=publish.nid)
book = Book.objects.create(name='西遊記',price=78,pub_date='2017-9-2',publish_id=3) # 多對多,添加關係add ,傳對應的(做者nid)id book.author.add(1,2) # 沒有返回值 # ret = book.author.add(3,6) # ret = book.author.add(*(3,6)) #add裏面能夠傳對象,也能夠傳多個,以逗號分隔,也能夠*(做者對象,做者對象) book = Book.objects.create(name='FOX',price=34,pub_date='2017-7-19',publish_id=3) author = Author.objects.filter(pk=7).first() book.author.add(author)
remove get
解除綁定關係(既能夠傳對象 又能夠傳author_id,既能夠傳多個又能夠傳一個) 移除一條或多條
book = Book.objects.filter(pk=8).first() # ret = book.author.remove(author.id) ret = book.author.remove(7) author = Author.objects.filter(pk=6).first() ret = book.author.remove(author) # ret = book.author.remove(2,5) # ret = book.author.remove(*(2,5))
clear 一次性解除所有綁定關係
book = Book.objects.filter(pk=8).first()
book.author.clear()
set 參數必須傳入可迭代對象,能夠傳id,也能夠傳對象
book = Book.objects.filter(pk=6).first() author = Author.objects.filter(pk=3).first() book.author.set([author]) #先執行clear,再執行add 先清空在添加
查詢安妮的電話號碼(正向查詢 按字段) # anni = Author.objects.filter(name='安妮').first() # print(anni.authordetail.phone,type(anni.authordetail)) 查詢電話號碼是 13956485512 的做者(反向查 按表名小寫) # authordetail = AuthorDetail.objects.filter(phone='13956485512').first() # print(authordetail.author) # print(authordetail.author.name)
#查詢紅樓夢是哪一個出版社 # 正向查 # 反向查 ''' A表book(關聯字段) B表 publish 正向查詢 A--->B 關聯字段在A,A去查詢B表,這叫正向查詢,按字段來查 反向查詢 B--->A 關聯字段在A,B去查詢A表,這叫正向查詢,按表名小寫_set ''' # 正向查詢 # book = Book.objects.filter(name='紅樓夢').first() # print(book.publish.name) # 反向查詢 # 北京出版社全部書 # publish = Publish.objects.filter(name='北京出版社').first() # print(publish.book_set.all())
#查詢紅樓夢這本書全部做者(正向 按字段) # book = Book.objects.filter(name='紅樓夢').first() # print(book.author.all()) #查詢張三出的全部書( 反向查 按表名小寫_set) # zs = Author.objects.filter(name='張三').first() # print(zs.book_set.all()) ''' A表book(關聯字段) B表 publish 正向查 A -->B 反向查 B -->A 總結: 正向查詢按字段 反向查詢按表名小寫告訴ORM引擎join那張表 一對一 正向: 按字段 反向: 按表名小寫 一對多 正向: 按字段 反向: 按表名小寫_set 多對多 正向: 按字段 反向: 按表名小寫_set '''
查詢北京出版社出版過的全部書籍價格、名字(反向 ) # ret = Publish.objects.filter(name='北京出版社').values('book__price','book__name') # print(ret) 正向 # res = Book.objects.filter(publish__name='北京出版社').values('name','price') # print(res)
#查詢王五出過的全部書籍名字、價格(多對多) #正向 # ret = Book.objects.filter(author__name='王五').values('name','author__name','author__authordetail__phone') # ret = Book.objects.filter(author__name='王五').values('name','price') # print(ret) #反向 # ret = Author.objects.filter(name='王五').values('book__name','book__price') # print(ret)
查詢王五的手機號(正向) # ret = Author.objects.filter(name='王五').values('authordetail__phone') # print(ret) #反向 按表名小寫 # ret = AuthorDetail.objects.filter(author__name='王五').values('phone') # print(ret)
''' 總結: 用__告訴ORM ,要鏈接哪一個表 一對一 正向: 按字段 反向:按表名小寫 一對多 正向: 按字段 反向:按表名小寫 多對多 正向: 按字段 反向:按表名小寫 ''' # 手機號以13開頭的做者出過的全部書籍名稱以出版社名稱 # ret = Book.objects.filter(author__authordetail__phone__startswith='13').values('name','publish__name') # print(ret) # ret = AuthorDetail.objects.filter(phone__startswith='13').values('author__book__name','author__book__publish__name') # print(ret) # ret = Author.objects.filter(authordetail__phone__startswith='13').values('book__name','book__publish__name') # print(ret) # ret = Publish.objects.filter(book__author__authordetail__phone__startswith='13').values('name','book__name') # print(ret)
聚合 aggregete # 計算全部圖書的平均價格 from django.db.models import Avg,Max,Min,Count,Sum # ret = Book.objects.all().aggregate(c=Avg('price')) # print(ret) # 計算全部圖書總價 # ret = Book.objects.all().aggregate(s=Sum('price')) # print(ret) # 最大價格 # ret = Book.objects.all().aggregate(m=Max('price')) # print(ret) # 全部圖書價格最大值個最小值,返回結果是字典 # ret = Book.objects.all().aggregate(b_max=Max('price'),b_min=Min('price')) # print(ret)
annotate()爲調用queryset中每個對象都生成獨立的統計值 #跨表分組查詢本質就是將關聯表join成一張表,再按單表的思路進行分組 from django.db.models import Avg,Max,Sum,Min,Count # 統計每本書的做者數 # book_list = Book.objects.all().annotate(author_num=Count('author','author')) # for book in book_list: # print(book.name,':',book.author_num) #同上 values 在這裏指group_by 的字段 ret = Book.objects.values('name').annotate(author_num=Count('author__name')).values('name','author_num') print(ret) # book_list = Book.objects.all().annotate(author_num=Count('author')).values('name','author_num') # print(book_list) # 統計每一出版社的最便宜的書 # ret = Publish.objects.all().annotate(p=Min('book__price')).values('name','p') # print(ret) # 統計每一本以 紅 開頭的書籍的做者個數 # ret = Book.objects.all().filter(name__startswith='紅').annotate(num=Count('author')).values('name','num') # print(ret) # ret = Book.objects.filter(name__startswith='西').annotate(num=Count('author')).values('name','num') # print(ret) # 統計不止一個做者的圖書:(做者數量大於1) # ****注意values在annotate前,表明group by的字段,不寫values 默認以基表的主鍵作group by 在後代我要select出來字段 # ret = Book.objects.all().values('name').annotate(num=Count('author__name')).filter(num__gt=1).values('name','num') # print(ret) # ret = Book.objects.all().annotate(num=Count('author')).filter(num__gt=1).values('name','num') # print(ret) # 根據一本圖書做者數量的多少對查詢集queryset進行排序 # ret = Book.objects.annotate(num=Count('author')).order_by('num').values('name','num') # print(ret) # 查詢各個做者出的書的總價格 # ret = Author.objects.all().annotate(p=Sum('book__price')).values('name','p') # print(ret) #查詢每一個出版社的名稱和書籍個數 # ret = Publish.objects.annotate(num=Count('book')).values('name','num') # print(ret)
F() 的實例能夠在查詢中引用字段,來比較同一個 model 實例中兩個不一樣字段的值。
# 查詢評論數大於收藏數的書籍 from django.db.models import F Book.objects.filter(commnetNum__lt=F('keepNum'))
Django 支持 F() 對象之間以及 F() 對象和常數之間的加減乘除和取模的操做。
# 查詢評論數大於收藏數2倍的書籍 Book.objects.filter(commnetNum__lt=F('keepNum')*2)
修改操做也可使用F函數,好比將每一本書的價格提升30元:
Book.objects.all().update(price=F("price")+30)
filter() 等方法中的關鍵字參數查詢都是一塊兒進行「AND」 的。 若是你須要執行更復雜的查詢(例如OR 語句),你可使用Q 對象。
名字叫花非花 或者price是39的數 | 或 & 和 ~ 非 # ret = Book.objects.all().filter(Q(name='花非花')|Q(price='39'))
你能夠組合& 和| 操做符以及使用括號進行分組來編寫任意複雜的Q 對象。同時,Q 對象可使用~ 操做符取反,這容許組合正常的查詢和取反(NOT) 查詢:
查詢函數能夠混合使用Q 對象和關鍵字參數。全部提供給查詢函數的參數(關鍵字參數或Q 對象)都將"AND」在一塊兒。可是,若是出現Q 對象,它必須位於全部關鍵字參數的前面。例如:
bookList=Book.objects.filter(Q(publishDate__year=2016) | Q(publishDate__year=2017), title__icontains="python")