一 . 創建外鍵
一對一創建外鍵python
外鍵名稱 = models.OneToOneField(to='要鏈接的類名', to_field='字段')
一對多創建外鍵mysql
外鍵名稱 = models.ForeignKey(to='要鏈接的類名',to_field='字段') # 外鍵要寫在一對多的 那個多的類 下面,好比一個老師對應不少學生,外鍵就要寫在學生的下面
多對多創建外鍵git
外鍵名稱 = models.ManyToManyField(to='另外一個類名') # 這個外鍵名稱(屬性)要寫在其中一個類的下面,而後to=另外一個類名, 這個外鍵就至關於第三張表(多對多創建外鍵必須經過第三張表)
二 . 多表查詢(基於子查詢)
# models.py建立表 class Author(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) age = models.IntegerField() # to後面加類名 to_field後面寫類名中的字段名 這是一對一的外鍵寫法 author_detail = models.OneToOneField(to='AuthorDetail', to_field='id') def __str__(self): return self.name class AuthorDetail(models.Model): id = models.AutoField(primary_key=True) addr = models.CharField(max_length=16) tel = models.IntegerField() class Publish(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) addr = models.CharField(max_length=16) class Book(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=16) price = models.DecimalField(max_digits=6,decimal_places=2) # 在Book上publish變成了publish_id 這是一對多的外鍵寫法 publish = models.ForeignKey(to='Publish',to_field='id') # 這個authors不是字段,他只是Book類裏面的一個屬性 這是多對多的創建第三張表的寫法 authors = models.ManyToManyField(to='Author')
對authors(第三張表的操做)sql
# 給id=1的書籍添加id=5和id=6這兩個做者 book_obj = models.Book.objects.filter(id=1)[0] book_obj.authors.add(*[5, 6]) # 數字的類型是int或者str都行 # 把id=1的書籍的做者所有刪掉 book_obj = models.Book.objects.filter(id=1)[0] book_obj.authors.clear() # 把id=1的書籍中的id=5和id=6的這兩個做者刪掉 book_obj = models.Book.objects.filter(id=1)[0] book_obj.authors.remove(*[5, 6]) # 把id=1的書籍中的做者名更新成id=7和id=8這兩個做者 book_obj = models.Book.objects.filter(id=1)[0] book_obj.authors.set([7, 8]) # set 不能用*[7, 8] set的執行流程是先把做者所有刪除,而後添加[7, 8]
一對一正向查詢(外鍵在哪一個表,他找別人就是正向)django
# 蕭峯的住址 author_obj = models.Author.objects.get(name='蕭峯') # author_obj.外鍵名.要查字段 print(author_obj.author_detail.addr) # author_detail = models.OneToOneField(to='AuthorDetail', to_field='id') # 這個author_detail就是外鍵名
一對一反向查詢(沒有外鍵的表查詢有外鍵的表就是反向查詢)app
# 地址是大理的英雄名字 author_detail_obj = models.AuthorDetail.objects.get(addr='大理') # author_detail_obj.要查詢的表名(要小寫).要查字段 print(author_detail_obj.author.name)
一對多正向查詢函數
# 出版天龍八部的出版社名字 book_obj = models.Book.objects.get(name='天龍八部') # book_obj.外鍵名.要查字段 print(book_obj.publish.name)
一對多反向查詢spa
# 查詢城市是西夏的出版社 出版的圖書 pub_obj = models.Publish.objects.get(city='西夏') # pub_obj.表名_set.all().values('name') 由於不止一個因此須要 表名_set print(pub_obj.book_set.all().values('name'))
多對多正向查詢code
# 天龍八部的做者都有誰 book_obj = models.Book.objects.get(name='天龍八部') # book_obj.第三張表的屬性.all().values(字段) print(book_obj.authors.all().values('name')) # 這個authors雖然在Book類下面,可是它不是字段,只是屬性.
多對多反向查詢對象
# 令狐沖寫了哪些書 author_obj = models.Author.objects.get(name='令狐沖') # author_obj.表名_all().values(字段) print(author_obj.book_set.all().values('name'))
三 .基於雙下劃線跨表查詢(基於join)
正向查詢按照外鍵名,反向查詢按照表名(小寫), 和上面的同樣,外鍵字段在哪一個表中, 他找別人就是正向,相反就是反向查詢
# 一對一查詢 # 查詢蕭峯做者的電話號 # 正向查詢 按照外鍵 "__" 這個是雙下劃線 # models.類名(表名).objects.filter(條件).values(外鍵名__字段) ret = models.Author.objects.filter(name='蕭峯').values('author_detail__tel') # 反向查詢 按照類名(小寫) # models.類名.objects.filter(另外一個類名(小寫)__條件).values(字段) ret = models.AuthorDetail.objects.filter(book__name='蕭峯').values('tel')
# 一對多查詢 # 金庸出版社出版過的全部書籍的名字 # 正向查詢 按照外鍵 # models.類名.objects.filter(外鍵名__條件).values(字段) ret = models.Book.objects.filter(publish__name='金庸出版社').values('name') # 反向查詢 按照類名(小寫) # models.類名.objects.filter(條件).values(另外一個類名(小寫)__字段) ret = models.Publish.objects.filter(name='金庸出版社').values('book__name')
# 多對多查詢 # 蕭峯這個做者寫了哪幾本書 # 正向查詢 按照外鍵 # models.類名.objects.filter(外鍵__條件).values(字段) ret = models.Book.objects.filter(authors__name='蕭峯').values('name') # 反向查詢 按照類名 # models.類名.objects.filter(條件).values(另外一個類名__字段) ret = models.Author.objects.filter(name='蕭峯').values('book__name')
# 連續跨表查詢
# 查詢金庸出版社出版的全部的書名及做者名 # 正向查詢 ret = models.Book.objects.filter(publish__name='金庸出版社').values('name','authors__name') # 反向查詢 ret = models.Publish.objects.filter(name='金庸出版社').values('book__name','book__authors__name') # 因爲Author和Publish兩個表沒有外鍵關係因此須要經過Book表找到做者名 # 電話以6開頭的做者出版過的書名及出版社名 # 正向查詢 ret = models.Book.objects.filter(authors__author_detail__tel__startswith='6').values('name','publish__name') # 反向查詢 # 方法一 ret = models.Publish.objects.filter(book__authors__author_detail__tel__startswith='6').values('name','book__name') # 方法二 ret = models.AuthorDetail.objects.filter(tel__startswith='6').values('author__book__name','author__book__publish__name') # 因爲Author與Book是多對多的關係,而且authors寫在Book下面,因此經過author往回找的時候直接author__book.
四 . 聚合查詢, 分組查詢, F查詢, Q查詢
聚合查詢
# aggregate(*args, **kwargs) 是queryset的終結,queryset對象後面.aggregate 獲得一個字典再也不是queryset對象 # 計算全部書的平均價格 from django.db.models import Avg models.Book.objects.all().aggregate(Avg('price')) # 也能夠給它起名字 aggregate(a = Avg('price')) # 這個objects後面的 all()寫不寫都行 能夠直接在控制器(models.Book.objects)後面寫 # 還能夠不止生成一個聚合函數 from django.db.models import Avg,Max,Min models.Book.objects.aggregate(Avg('price'),Max('price'),Min('price'))
分組查詢
------------------單表查詢(用上邊的Book表)---------------------- # 查詢每一個出版社出版了多少本書 annotate裏面寫聚合函數(Max,Min,Avg,Count) 獲得一個queryset對象 models.Book.objects.values('publish').annotate(c=Count('id')) # values裏面寫的是要分組的字段,每一個出版社意思就是以出版社爲分組, annotate裏面寫你要統計的, 並且必須是 別名=聚合函數這個格式 ------------------多表查詢(用以前那些表) --------------------- 查詢每一個出版社出版了多少本書 models.Publish.objects.values('name').annotate(c=Count('book__id')) # 下面這個方法比較經常使用 models.Publish.objects.annotate(c=Count('book__id')).values('name','c') # 若是用上邊的那個方法出現關於group by的錯誤的話,須要進行一下操做: 進入mysql裏執行SELECT @@GLOBAL.sql_mode; 看看裏面是否有 ONLY_FULL_GROUP_BY參數,若是有的話須要到配置文件中(my.ini或者是mysql.cnf)修改 sql_mode ='STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION' 而後重啓mysql.
F查詢(能夠進行兩個字段的比較)
# 好比說在Book表裏面加上評論數comment_num 和點贊數support_num # 查詢評論數大於點贊數的書 from django.db.models import F models.Book.objects.filter(comment_num__gt=F('support_num')) # django 還支持F()對象之間以及F()對象與常數之間的加減乘除 models.Book.objects.filter(comment_num__gt=F('support_num')*2) # 也能夠用F()來進行修改 # 把每本書的價格添加1000 models.Book.objects.update(price=F('price')+1000)
Q查詢
像filter()中的條件一塊兒查詢的時候都是and, 若是想要有or的關係就須要用到Q查詢
Q對象可使用$(and) |(or) ~(not) 操做組合起來. 當一個操做符用在兩個Q對象上面時,這兩個Q對象因爲操做符的做用就變成了一個新的對象. # 查詢做者名字爲蕭峯或者段譽出版的書 models.Book.objects.filter(Q(authors__name='蕭峯')|Q(authors__name='段譽')) # 能夠組合其餘的操做符進行操做 # 查詢做者是蕭峯或者是段譽價格不高於100的書 models.Book.objects.filter(Q(author__name='蕭峯')|Q(author__name='段譽')& ~Q(price__gt=100)) # 若是有關鍵字參數和Q查詢同時在篩選條件裏面,Q查詢必需要寫到關鍵字參數前面 # 查詢做者名字是蕭峯或者是段譽的價格爲100 的書 models.Book.objects.filter(Q(author__name='蕭峯')|Q(author__name='段譽'),price=100) # 這個關鍵字參數要寫到Q查詢的後面,中間用逗號隔開,表示and的意思
五 . python腳本中調用Django環境(django外部腳本使用models)
import os if __name__ == '__main__': os.environ.setdefault("DJANGO_SETTINGS_MODULE", "BMS.settings") import django django.setup() from app01 import models #引入也要寫在上面三句以後 books = models.Book.objects.all() print(books)