day055&056Django之多表操做,多表查詢

本節內容:

一、回顧一對1、一對多、多對多的表結構關係
二、建立模型
三、添加表記錄
四、基於對象的跨表查詢
五、基於雙下劃線的跨表查詢
六、聚合查詢與分組查詢
七、F查詢與Q查詢

1、回顧一對1、一對多、多對多的表結構關係

一、一對多關係表

一本書只有一個出版社,一個出版社能夠出版多本書
關聯字段在「多」的表中
book
id  title  publish_id
1 java 1 2 go 1 publish id name email addr 1 AAA 123 bejing 
SQL

二、多對多建立關係表

表之間的關係,書和做者的關係,一本書能夠有多個做者,一個做者能夠有多本書
多對多建立關係表
     Book表
     id  title  publish_id
      1 java 1 2 go 1 Author表 id name 1 alex 2 yuan book2author對應關係表(藉助第三張表) id book_id author_id 1 1 1 2 1 2 3 2 2 
SQL

三、一對一關係表

關聯字段能夠創建在任意表下,但必須惟一約束。
Author
    id name  ad_id(unique約束) 1 alex 1 2 yuan 2 AuthorDetail id gender addr gf ID author_id 1 male beijing 鐵錘 131 1 2 male beijing 鋼彈 151 2 
SQL

2、建立模型

一、 實例:圖書管理

咱們來假定下面這些概念,字段和關係

做者模型:一個做者有姓名和年齡。

做者詳細模型:
把做者的詳情放到詳情表,包含生日,手機號,家庭住址等信息。
做者詳情模型和做者模型之間是一對一的關係(one-to-one)

出版商模型: 出版商有名稱,所在城市以及email。

書籍模型:  書籍有書名和出版日期,
一本書可能會有多個做者,一個做者也能夠寫多本書,因此做者和書籍的關係就是多對多的關聯關係(many-to-many); 一本書只應該由一個出版商出版,因此出版商和書籍是一對多關聯關係(one-to-many) 
Bash
book這個app下的models.py文件代碼
from django.db import models # Create your models here. class Book(models.Model): title = models.CharField( max_length=32) pub_date=models.DateField() price=models.DecimalField(max_digits=5,decimal_places=2) # 與Publish創建一對多的關係,外鍵字段創建在多的一方 publish=models.ForeignKey(to="Publish",to_field="id",on_delete=models.CASCADE,null=True) # 字段名默認爲,publish_id ,on_delete級聯刪除,刪一個其餘的跟着刪除 # 與Author表創建多對多的關係,ManyToManyField能夠建在兩個模型中的任意一個,自動建立第三張表 authors=models.ManyToManyField("Author",db_table="book2authors") # 建立關係表, db_table關係表的名字能夠在這裏設定 def __str__(self): return self.title class Publish(models.Model): name=models.CharField( max_length=32) city=models.CharField( max_length=32) email=models.CharField(max_length=32) def __str__(self): return self.name class Author(models.Model): name=models.CharField( max_length=32) age=models.IntegerField() #books=models.ManyToManyField("Book") ad=models.OneToOneField("AuthorDetail",null=True,on_delete=models.CASCADE) def __str__(self): return self.name class AuthorDetail(models.Model): birthday=models.DateField() telephone=models.BigIntegerField() addr=models.CharField( max_length=64) # author=models.OneToOneField("Author",on_delete=models.CASCADE) def __str__(self): return str(self.telephone) 
Python

二、寫這個表格對象的python代碼的—注意事項

一、表的名稱myapp_modelName,是根據 模型中的元數據自動生成的,
也能夠覆寫爲別的名稱,就是重命名

二、id字段默認會自動添加且爲主鍵,能夠不寫,

三、對於外鍵字段,Django 會在字段名上添加"_id" 來建立數據庫中的列名 因此咱們在寫外鍵字段時,就只寫關聯的表名 四、這個例子中的CREATE TABLE SQL 語句使用PostgreSQL 語法格式, 要注意的是Django 會根據settings 中指定的數據庫類型來使用相應的SQL 語句。 五、定義好模型以後,你須要告訴Django _使用_這些模型。 你要作的就是修改配置文件中的INSTALL_APPSZ中設置,在其中添加models.py所在應用的名稱 六、外鍵字段 ForeignKey 有一個 null=True 的設置(它容許外鍵接受空值 NULL),你能夠賦給它空值 None 。 
Bash

2、添加表記錄

添加記錄前的準備工做,建立好數據庫,
一、選擇MySQL數據庫(經常使用),仍是sqlite3數據庫,看需求。 DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME':'day056orm', # 要鏈接的數據庫,鏈接前須要建立好 'USER':'root', # 鏈接數據庫的用戶名 'PASSWORD':'123', # 鏈接數據庫的密碼 'HOST':'127.0.0.1', # 鏈接主機,默認本級 'PORT':3306 # 端口 默認3306 }, } 注意:使用MySQL數據庫時記得在啓動文件夾下的__init__文件中, 添加import pymysql pymysql.install_as_MySQLdb() 而後啓動python manage.py makemigrations命令和python manage.py migrate 就建立好了,咱們寫好的表結構。 
Bash

一、建立一些基礎表(被關聯的表)

建立publish表

建立author表

建立authordetail表:
java

二、綁定關係

首先在urls.py中綁定好urls分發,path('add/',views.add),
在book的app下建立好,def add(request):視圖函數

一、綁定一對多的關係

建立表記錄及綁定其對應的關係
def add(request): # 綁定一對多關係 # 建立書籍和出版社 # 方式1: # book=models.Book.objects.create(title="linux",price=122,pub_date="2012-12-12",publish_id=1) # 方式2: # pub_obj=models.Publish.objects.filter(name="人民出版社").first() # 拿到publish對象 # book=models.Book.objects.create(title="python",price=223,pub_date="2012-11-11",publish=pub_obj) # print(book.publish_id) # print(book.publish) # book書籍的出版社對象 # 查詢python書籍的出版社的郵箱 # 方式1,雙下劃線查詢 # email=models.Book.objects.filter(title="python").values("publish__email") # print(email) # email=models.Publish.objects.filter(id=book.publish_id).first().email # book是上面的表記錄對象 # print(email) # print(book.publish.email) return HttpResponse("建立成功") 核心: book.publish和book.publish_id具體是什麼? 一、book.publish # 直接拿到的是出版社對象, 二、book.publish_id # 拿到是出版社對象對應的id 
Python

二、綁定多對多關係

綁定多對多的關係, 無非就是在關係表中建立記錄
綁定多對多關係
# linux這本書綁定兩個做者: alex,egon # linux=models.Book.objects.filter(title="linux").first() # alex=models.Author.objects.filter(name="alex").first() # egon=models.Author.objects.filter(name="egon").first() # linux.authors.add(alex,egon) # Book對象直接點外鍵字段,就能夠找到第三張關係表 # # linux.authors.add(1) # 爲這個Book對象添加一個做者, # linux.authors.add(*[1,2]) # 打散列表,爲該書籍添加列內的全部做者 # # linux.authors.remove(alex,) # 爲該書籍刪除一個做者 # linux.authors.clear() # 清空該Book對象的關係表的關聯關係 # # linux.authors.set([1,]) # set先清空以前全部的記錄(做者),從新寫入,相似於文件寫入前清空 # 綁定多對多關係,重點是在關係表上建立記錄,作好兩個表之間的對應關係 ######### 正向操做按字段,反向操做按表名小寫 linux = models.Book.objects.filter(title='linux').first() go = models.Book.objects.filter(title="go").first() alex = models.Author.objects.filter(name="alex").first() # 給alex做者綁定兩本書籍: linux,go alex.book_set.add(linux,go) # 單個的時候直接操做,多個對象是使用_set操做 核心:book_obj.authors.all()是什麼? 待續 
Python

4、基於對象的跨表查詢

一 基於對象的跨表查詢( 子查詢:以上一次的查詢結果做爲下一次的查詢條件) (1)一對多 正向查詢:按字段 book.publish Book對象(多)---------------------------------- > Publish 對象 <--------------------------------- 反向查詢:按表名小寫_set.all() (2)多對多 正向查詢:按字段 book.authors.all() Book對象 ---------------------------------- > Author 對象 <--------------------------------- 反向查詢:按表名小寫_set.all() (2)一對一 正向查詢:按字段 book.ad Author 對象 ---------------------------------- > AuthorDetail 對象 <--------------------------------- 反向查詢:按表名小寫 
Bash
基於對象的跨表查詢
def query(request): #(1)一對多 # 1 查詢linux這本書的出版社的城市(正向查詢) # book=models.Book.objects.filter(title='linux').first() # print(book.publish.city) # Book對象直接點外鍵字段就是出版社對象,直接點城市就好了 # 2 查詢人民出版社出版的全部書籍(反向查詢) # publish=models.Publish.objects.filter(name='人民出版社').first() # queryset=publish.book_set.all() # 這是拿到的是一個集合 # print(queryset) # <QuerySet [<Book: linux>, <Book: python>]> # 二、多對多 # 1 查詢linux書籍的全部做者(正向查詢) # linux=models.Book.objects.filter(title="linux") # queryset=linux.authors.all() # 這樣就能夠拿到全部的書籍對象集合,由於設置了__str__ # print(queryset) # 2 查詢alex做者出版過的全部書籍 # alex=models.Author.objects.filter(name='alex').first() # 記得從集合中取出第一個對象 # queryset=alex.book_set.all() # 反向查詢表名_set # print(queryset) # <QuerySet [<Book: linux>]> # 3 一對一 # 1 查詢alex的手機號 # alex=models.Author.objects.filter(name="alex").first() # print(alex.ad.telephone) # 2 查詢手機號爲110的做者的名字 # tel=models.AuthorDetail.objects.filter(telephone=911).first() # print(tel.author.name) # 不是集合對象,直接表名(小寫).出來 return HttpResponse("查詢成功") 
Python

5、基於雙下劃線的跨表查詢

KEY:通知ORM引擎如何跨表: 正向查詢按字段,反向查詢按表名小寫
基於雙下劃線的跨表查詢
def query(request): # 一、查詢linux這本書的出版社地址 # 方式1 正向查詢 # queryset=models.Book.objects.filter(title="linux").values("publish__city") # print(queryset) # filter獲得的queryset集合對象 # 方式2 反向查詢 # queryset=models.Publish.objects.filter(book__title="linux").values("city") # print(queryset) # 2 查詢linux書籍的全部做者 # queryset=models.Book.objects.filter(title="linux").values("authors__name") # queryset=models.Book.objects.filter(title__startswith="li").values("authors__name") # 重點 # print(queryset) # queryset=models.Author.objects.filter(book__title="linux").values("name") # 反向查詢 # 3 查詢alex的手機號 # queryset=models.Author.objects.filter(name="alex").values("ad__telephone") # 正向 # queryset=models.AuthorDetail.objects.filter(author__name="alex").values("telephone") # 反向 # print(queryset) # 連續跨表 # 4 查詢人民出版社出版過的全部書籍的名字及做者的姓名 queryset=models.Book.objects.filter(publish__name="人民出版社").values("title","authors__name") # 正向查詢 # queryset=models.Author.objects.filter(book__publish__name="人民出版社").values("book__title","name") # 反向查詢 # 默認都是left join,因此若是有存在的左邊基準的值爲空,那麼就會不保留這條記錄 print(queryset) return HttpResponse("查詢成功")
相關文章
相關標籤/搜索