Django基礎五之Django模型層(二)多表操作
Django基礎五之Django模型層(二)多表操作
一 建立模型
表和表之間的關係
一對一、多對一、多對多
# 作者表 比較常用的資訊放在這個表中 class Author(models.Model): name=models.CharField(max_length=32) age=models.IntegerField() authorDetail=models.OneToOneField(to='AuthorDetail') #與AuthorDetail建立一對一的關係,一對一的這個關係欄位寫在這兩個表的任意一個表裡面都可以,models.OneToOneField(to='AuthorDetail')就是foreignkey+unique,只不過不需要我們自己來寫引數了,並且orm會自動幫你給這個欄位名字拼上一個_id,資料庫中欄位名稱為authorDetail_id也可以寫成這樣# authorDetail = models.OneToOneField(to="AuthorDetail", to_field="id",on_delete=models.CASCADE) on_delete=models.CASCADE級聯關係 def __str__(self): return self.name # 作者資訊表 不常用的作者資訊放這個表中 class AuthorDetail(models.Model): brithday=models.DateField() telephone=models.BigIntegerField() addr=models.CharField(max_length=64) def __str__(self): return self.addr # 書籍出版社表 class Publish(models.Model): name=models.CharField(max_length=32) city=models.CharField(max_length=32) email=models.EmailField() def __str__(self): return self.name # 書籍表 class Book(models.Model): title=models.CharField(max_length=32) publishDate=models.DateField() price=models.DecimalField(max_digits=5,decimal_palces=2) # 與Publish建立一對多的關係,外來鍵欄位建立在多的一方,欄位publish如果是外來鍵欄位,那麼它自動是int型別 # foreignkey裡面可以加很多的引數,都是需要咱們學習的,慢慢來,to指向表,to_field指向你關聯的欄位,不寫這個,預設會自動關聯主鍵欄位,on_delete級聯刪除欄位名稱不需要寫成publish_id,orm在翻譯foreignkey的時候會自動給你這個欄位拼上一個_id,這個欄位名稱在資料庫裡面就自動變成了publish_id publish=models.Foreignkey(to='publish') # 與Author表建立多對多的關係,ManyToManyField可以建在兩個模型中的任意一個,自動建立第三張表,並且注意一點,你檢視book表的時候,你看不到這個欄位,因為這個欄位就是建立第三張表的意思,不是建立欄位的意思,所以只能說這個book類裡面有authors這個欄位屬性 authors=models.ManyToManyField(to='Author') def __str__(self): return self.title # 多對多的表關係,我們學mysql的時候是怎麼建立的,是不是手動建立一個第三張表,然後寫上兩個欄位,每個欄位外來鍵關聯到另外兩張多對多關係的表,orm的manytomany自動幫我們建立第三張表,兩種方式建立關係都可以,以後的學習我們暫時用orm自動建立的第三張表,因為手動建立的第三張表我們進行orm操作的時候,很多關於多對多關係的表之間的orm語句方法無法使用 # 如果你想刪除某張表,你只需要將這個表登出掉,然後執行那兩個資料庫同步指令就可以了,自動就刪除了。 #注意不管是一對多還是多對多,寫to這個引數的時候,最後後面的值是個字串,不然你就需要將你要關聯的那個表放到這個表的上面
多表間的增刪改查
新增表記錄---增
操作前先簡單的錄入一些資料:還是create和save兩個方法,和單表的區別就是看看怎麼新增關聯欄位的資料
一對一 方式一: new_author_detail=models.AuthorDetail.objects.create( birthday='1965-10-10', telephone='18335267641', addr='山西大同' ) models.Author.objects.create( name='ll', age='53', authorDetail=new_author_detail, ) 方式二 常用 obj=models.AuthorDetail.objects.filter(addr='山西大同').last() print(obj.id) models.Author.objects.create( name='mx', age='52', authorDetail_id=obj.id ) 一對多 obj=models.Publish.objects.get(id=3) models.Book.objects.create( title='故事會新編', publishDate='2019-9-10', price=30, # 方式一 publish=obj # 方式二 常用 publish_id=obj.id ) 多對多 方式一 常用 book_obj=models.Book.objects.get(id=1) book_obj.authors.add(*[1,2]) #打散 方式二 author1=models.Author.objects.get(id=3) author2=models.Author.objects.get(id=4) book_obj=models.Book.objects.get(id=4) book_obj.authors.add(*[author1,author2])
刪除表記錄---刪
一對一 models.AuthorDetail.objects.get(id=6).delete() models.Author.objects.get(id=5).delete() 一對多 models.Publish.objects.get(id=1).delete() models.Book.objects.get(id=1).delete() 多對多 book_obj = models.Book.objects.get(id=1) book_obj.authors.remove(*[1, 2]) #刪除 book_obj.authors.clear() #清空 book_obj.authors.add(2,) #新增 book_obj.authors.set(['1','2']) #刪除然後更新
更新表記錄---改
一對一
models.Author.objects.filter(id=1).update(
name='安文',
age=24,
方式一
# authorDetail_id=5,
方式二
authorDetail=models.AuthorDetail.objects.get(id=3)
)
一對多
models.Book.objects.filter(id=4).update(
title='java核心',
方式一
publish_id=4,
方式二
publish=models.Publish.objects.get(id=2)
)
多對多
book_obj.authors.set(['1','2']) #刪除然後更新
查詢表記錄---查
基於物件的跨表查詢 -- 類似於子查詢
正向查詢和反向查詢
| 關係屬性(欄位)寫在那個表中,從當前表(類)的資料去查詢它關聯表(類)中的資料叫正向查詢,反之叫反向查詢 |
#一對一
正向查詢
# 查詢yage的電話
author_obj=models.Author.objects.filter(name='yage').first()
print(author_obj.authorDetail)
print(author_obj.authorDetail.telepbone)
反向查詢
# 查詢這個電話 145523669874 是誰的
author_detail_obj=models.AuthorDertail.objects.get(telrphone=145523669872)
print(author_detail_obj.author)
print(author_detail_obj.author.name)
"""
正向查詢Author_obj.authorDateil,物件.關聯屬性
Author------------------------->AuthorDateil
Author<-------------------------AuthorDateil
反向查詢:AuthorDateil.author,物件.小寫類名
"""
#一對多
正向查詢
# 查詢某本書 java核心 的 出版社是哪個
book_obj=models.Book.objects.get(title='java核心')
print(book_obj.publish)
print(book_obj.publish.name)
反向查詢
#清華出版社出版的那些書
pub_pbj=models.Publish.objects.get(name='清華出版社')
print(pub_obj.book_set.all())
"""
正向查詢 book_obj.publishs 物件.屬性
Book------------------------------>>>Publish
Book<<<------------------------------Publish
反向查詢 pub_obj.book_set.all() 物件.表名小寫_set
"""
#多對多
正向查詢
# 查詢某本書 java核心 是誰出版的
book_obj=models.Book.objects.get(title='java核心')
print(book_obj.authors.all())
反向查詢
#查詢 yage 寫了哪些書
author_obj=models.Author.object.get(name='yage')
print(author_obj.book_set.all())
"""
正向查詢 book_obj.authors.all() 物件.屬性
book --------------->author
book <---------------author
反向查詢 author_obj.book_set.all() 物件.表名小寫_set
"""
基於雙下劃線的跨表查詢--連表查詢 join
Django 還提供了一種直觀而高效的方式在查詢(lookups)中表示關聯關係,它能自動確認 SQL JOIN 聯絡。要做跨關係查詢,就使用兩個下劃線來連結模型(model)間關聯欄位的名稱,直到最終連結到你想要的model 為止。
'''
基於雙下劃線的查詢就一句話:正向查詢按欄位,反向查詢按表名小寫用來告訴ORM引擎join哪張表,一對一、一對多、多對多都是一個寫法,注意,我們寫orm查詢的時候,哪個表在前哪個表在後都沒問題,因為走的是join連表操作。
'''
# 一對一
#1. 查詢yage的電話
# 方式一 正向查詢
obj=models.Author.object.filter(name='yage').values('authorDetail__telepbone')
print(obj)
# 方式二 反向查詢
obj=models.AuthorDetail.objects.filter(author__name='yage').values('telephone')
print(obj)
#2. 誰的電話是 145523669874
obj=models.AuthorDetail.object.filter(telephon='145523669874').values('authors__name')
print(obj)
obj=models.Author.objects.filter(authorDetail__telephon='145523669874').values('name')
print(obj)
# 一對多
# 查詢某本書 java核心 的 出版社是哪個
obj=models.Book.objects.filter(name='java核心').values('publish__name')
obj=models.Publish.objects.filter(book__title='java核心').values('name')
# 清華出版社出版的那些書
obj=models.Publish.objects.filter(name='清華出版社').values('book__title')
print(obj)
obj=models.Book.object.filter(publish__name='清華出版社').values('title')
print(obj)
# 多對多
# 查詢某本書 java核心 是誰出版的
obj=models.Book.objects.filter(title='java核心').values('authors__name')
print(obj)
obj=models.Author.objects.filter(book__title='java核心').values('name')
print(obj)
# 查詢 yage 寫了哪些書
#方法一
obj=models.Author.objects.filter(name='yage').values('book__title')
print(obj)
#方法二
obj=models.Book.objects.filter(authors__name='yage').values('title')
print(obj)
#進階查詢一
#清華出版社 出版的書 以及作者姓名
#方法一
obj=models.Publish.objects.filter(name='清華出版社').values('book__title','book__authors__name')
print(obj)
#方法二
obj=models.Book.objects.filter(publish__name='清華出版社').values('title','authors__name')
print(obj)
#方法三
obj=models.Author.objects.filter(book__publish__name='清華出版社').values('name','book__title')
print(obj)
進階查詢二
#手機號以 14552 開頭的作者 出版過的所以書籍名稱 以及 出版社名稱
#方法一
obj=models.AuthorDetail.objects.filter(telephone__startswith='14552').values('author__book__title' , 'author__book__publish__name')
print(obj)
#方法二
obj=models.Author.objects.filter(authorDetail__telephone__startswith='14552').values('book__title','book__publish__name')
print(obj)
#方法三
obj=models.Book.objects.filter(authors__authorDetail__telephone__startswith='14552').values('authors__book__title','authors__book__publish__name')
print(obj)
related_name
反向查詢時,如果定義了related_name ,則用related_name替換 表名,例如:
publish = ForeignKey(Book, related_name='bookList')
# 練習: 查詢人民出版社出版過的所有書籍的名字與價格(一對多)
# 反向查詢 不再按表名:book,而是related_name:bookList
obj=models.Publish.objects.filter(name="清華出版社").values("bookList__title","bookList__price")
聚合函式
from django.db.models import Avg,Min,Max ,Sum,Count
# 計算所有書籍的平均價格 圖書價格的最大值
#aggregate()是QuerySet 的一個終止子句,意思是說,它返回一個包含一些鍵值對的字典。鍵的名稱是聚合值的識別符號,值是計算出來的聚合值。鍵的名稱是按照欄位和聚合函式的名稱自動生成出來的。如果你想要為聚合值指定一個名稱,可以向聚合子句提供它。
obj=models.Book.objects.all().aggregate(a=Avg('price'),m=Max('price'))
print(obj) #{'a': 47.5, 'm': Decimal('78.00')}
print(obj['m']-2) #76.00
分組查詢
# 統計每個出版社出版的書籍的平均價格
ret=models.Book.objects.values('publish_id').annotate(a=Avg('price'))
print(ret) #<QuerySet [{'publish_id': 2, 'a': 69.0}, {'publish_id': 3, 'a': 30.0}, {'publish_id': 4, 'a': 22.0}]>
ret=models.Publish.objects.annotate(a=Avg('book__price'))
print(ret) #<QuerySet [<Publish: 山西出版社>, <Publish: 清華出版社>, <Publish: 江蘇出版社>]>
ret = models.Publish.objects.annotate(a=Avg('book__price')).values('name', 'a')
print(ret) #<QuerySet [{'name': '山西出版社', 'a': 22.0}, {'name': '清華出版社', 'a': 69.0}, {'name': '江蘇出版社', 'a': 30.0}]>
F查詢
在上面所有的例子中,我們構造的過濾器都只是將欄位值與某個常量做比較。如果我們要對兩個欄位的值做比較,那該怎麼做呢?我們在book表裡面加上兩個欄位:評論數:comment,收藏數:good
#查詢點贊數大於評論數的書籍
ret=models.Book.objects.filter(good__gt=F('comment'))
# 查詢點贊數大於評論數+20的書籍
#Django 支援 F() 物件之間以及 F() 物件和常數之間的加減乘除和取模的操作。
ret=models.Book.objects.filter(good__gt=F('comment')+20)
print(ret) #<QuerySet [<Book: 今天是個好日子>, <Book: java核心>]>
#所有書籍的價格+20
models.Book.objects.all().update(price=F('price')+20)
#評論數大於100,和 ,點贊數大於100的
ret=models.Book.objects.filter(good__gt=100,comment__gt=100)
print(ret) #<QuerySet [<Book: java核心>, <Book: 故事會新編>]>
Q查詢
Q
物件可以使用&(與)
、|(或)、~(非)
操作符組合起來。當一個操作符在兩個Q
物件上使用時,它產生一個新的Q
物件。
你可以組合&
和|
操作符以及使用括號進行分組來編寫任意複雜的Q
物件。同時,Q
物件可以使用~
操作符取反,這允許組合正常的查詢和取反(NOT
) 查詢:
#評論數大於100,或者 點贊數大於100的
ret=models.Book.objects.filter(Q(good__gt=100)|Q(comment__gt=100))
print(ret) #<QuerySet [<Book: java核心>, <Book: 故事會新編>, <Book: LINUX學習>]>
#評論數大於100,或者 點贊數小於等於100的
ret = models.Book.objects.filter(~Q(good__gt=100) | Q(comment__gt=100))
print(ret)
#評論數大於100,或者 點贊數大於100的 且 price='42'
#逗號連線的普通查詢條件放在最後
#查詢函式可以混合使用Q 物件和關鍵字引數。所有提供給查詢函式的引數(關鍵字引數或Q 物件)都將"AND”在一起。但是,如果出現Q 物件,它必須位於所有關鍵字引數的前面。例如:
ret = models.Book.objects.filter(Q(good__gt=100) | Q(comment__gt=100),price='42')
print(ret)
#評論數大於100,或者 點贊數大於100的 且 price='42'
ret = models.Book.objects.filter(Q(good__gt=100) | Q(comment__gt=100) & Q(price='42')) #&優先順序高
ret = models.Book.objects.filter(Q(Q(good__gt=100) | Q(comment__gt=100)) & Q(price='42')) #|優先順序高
orm執行原生sql語句
在模型查詢API不夠用的情況下,我們還可以使用原始的SQL語句進行查詢。
Django 提供兩種方法使用原始SQL進行查詢:一種是使用raw()方法,進行原始SQL查詢並返回模型例項;另一種是完全避開模型層,直接執行自定義的SQL語句。
執行原生查詢
raw()管理器方法用於原始的SQL查詢,並返回模型的例項:
注意:raw()語法查詢必須包含主鍵。
這個方法執行原始的SQL查詢,並返回一個django.db.models.query.RawQuerySet 例項。 這個RawQuerySet 例項可以像一般的QuerySet那樣,通過迭代來提供物件例項。
ret=models.Publish.objects.raw('select * from app01_publish;')
print(ret) #<RawQuerySet: select * from app01_publish;>
for i in ret:
print(i.name)
# 直接執行自定義SQL
# django提供的介面中獲取資料庫連線,然後像使用pymysql模組一樣操作資料庫
from django.db import connection, connections
cursor = connection.cursor() # cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
ret = cursor.fetchone()
檢視orm生成原生sql語句
ret=models.Publish.objects.all()
print(ret)
from django.db.models import connection
print(connection.queries)
綜合查詢練習題
#1 查詢每個作者的姓名以及出版的書的最高價格
ret=models.Author.objects.values('name').annotate(max_price=Max('book__price'))
print(ret) #注意:values寫在annotate前面是作為分組依據用的,並且返回給你的值就是這個values裡面的欄位(name)和分組統計的結果欄位資料(max_price)
#ret=models.Author.objects.annotate(max_price=Max('book__price')).values('name','max_price')#這種寫法是按照Author表的id欄位進行分組,返回給你的是這個表的所有model物件,這個物件裡面包含著max_price這個屬性,後面寫values方法是獲取的這些物件的屬性的值,當然,可以加雙下劃線來連表獲取其他關聯表的資料,但是獲取的其他關聯表資料是你的這些model物件對應的資料,而關聯獲取的資料可能不是你想要的最大值對應的那些資料
# 2 查詢作者id大於2作者的姓名以及出版的書的最高價格
ret=models.Author.objects.filter(id__gt=2).annotate(max_price=Max('book__price')).values('name','max_price')#記著,這個values取得是前面呼叫這個方法的表的所有欄位值以及max_pirce的值,這也是為什麼我們取關聯資料的時候要加雙劃線的原因
print(ret)
#3 查詢作者id大於2或者作者年齡大於等於20歲的女作者的姓名以及出版的書的最高價格
ret=models.Author.objects.filter(Q(id__gt=2)|Q(age__gte=20),sex='female').annotate(max_price=Max('book__price')).values('name','max_price')
#4 查詢每個作者出版的書的最高價格 的平均值
ret=models.Author.objects.values('id').annotate(max_price=Max('book__price')).aggregate(Avg('max_price')) #{'max_price__avg': 555.0} 注意,aggregate是queryset的終止句,得到的是字典
ret=models.Author.objects.annotate(max_price=Max('book__price')).aggregate(Avg('max_price')) #{'max_price__avg': 555.0} 注意,aggregate是queryset的終止句,得到的是字典
補充
url.py 中的url(r'^admin/', admin.site.urls)路由操作admin.py
app應用中admin.py
from django.contrib import admin
from app01 import models
# Register your models here.
admin.site.register(models.Book)
admin.site.register(models.Author)
admin.site.register(models.AuthorDetail)
admin.site.register(models.Publish)
點選Tools 中run manage.py task 執行createsuperuser建立一個超級使用者(username和password),然後可以訪問http://127.0.0.1:8000/admin/ ,可以直接操作資料庫進行增刪改查。
| 訪問http://127.0.0.1:8000/admin/ |
相關推薦
Django基礎五之Django模型層(二)多表操作
Django基礎五之Django模型層(二)多表操作 一 建立模型 表和表之間的關係 一對一、多對一、多對多 # 作者表 比較常用的資訊放在這個表中 class Author(models.Model): name=models.CharField(max_length=32) ag
Django基礎五之django模型層(一)單表操作
Django基礎五之django模型層(一)單表操作 一 ORM簡介 MVC或者MVC框架中包括一個重要的部分,就是ORM,它實現了資料模型與資料庫的解耦,即資料模型的設計不需要依賴於特定的資料庫,通過簡單的配置就可以輕鬆更換資料庫,這極大的減輕了開發人員的工作量,不需要面對因資料庫變更而導致的無效勞動 O
05.Django基礎五之django模型層(一)單表操作
一 ORM簡介 MVC或者MVC框架中包括一個重要的部分,就是ORM,它實現了資料模型與資料庫的解耦,即資料模型的設計不需要依賴於特定的資料庫,通過簡單的配置就可以輕鬆更換資料庫,這極大的減輕了開發人員的工作量,不需要面對因資料庫變更而導致的無效勞動 ORM是“物件-關係-對映”的簡稱。(Object
web框架開發-Django模型層(2)-多表操作
增加 關系模型 進行 true ... 匹配條件 西遊記 port 覆寫 很重要,都是精華多表關系模型一對一一旦確定表關系是一對一,在兩張表中的任意一張表中建立關聯字段+Unique一對多一旦確定表關系是一對多,創建關聯字段在多的表中多對多一旦確定表關系是多對多,創建第三章
django模型層2 多表操作
digits 名稱 alt req 最大 app 聚合 員工 postgre 1.多表操作: 1.創建模型: 實例:我們來假定下面這些概念,字段和關系 作者模型:一個作者有姓名和年齡。 作者詳細模型:把作者的詳情放到詳情表,包含生日,手機號,家庭住址等信息。作者
Django模型層(多表操作)
創建 gif 唯一性 add 技術分享 pri 生成 res 自動 創建模型 (一)多表查詢 一對一:models.OneToOneField(to_field=‘id‘,to=‘Authordatil‘) 一對多:(外鍵設置唯一性) m
9.18 模型層二 --多表關係
7.3 多表操作 一、建立模型 例項:我們來假定下面這些概念,欄位和關係作者模型:一個作者有姓名和年齡。作者詳細模型:把作者的詳情放到詳情表,包含生日,手機號,家庭住址等資訊。作者詳情模型和作者模型之間是一對一的關係(one-to-one)出版商模型:出版商有名稱,所在城市以及email。書籍模型: 書籍
Django基礎篇之數據庫選擇及相關操作
setting 必須 需要 mysql pyc -- creates 127.0.0.1 settings 在djanjo框架中我們最常用的框架分別就是mysql和sqlit了,下面我們將分別講述一下這倆種數據庫的基礎必備知識 mysql 一、利用命令創建(在終端上執行)
django-模型層(model)-多表相關操作(圖書管理練習)
brush height cit query == es2017 blank res name 66、django之模型層(model)--多表相關操作(圖書管理小練習) 前面幾篇隨筆的數據庫增刪改查操作都是在單表的操作上的,然而現實中不可能都是單表操作,更多的是多表操作,
Django模型層:多表查詢
一 建立模型 例項:我們來假定下面這些概念,欄位和關係 作者模型:一個作者有姓名和年齡。 作者詳細模型:把作者的詳情放到詳情表,包含生日,手機號,家庭住址等資訊。作者詳情模型和作者模型之間是一對一的關係(one-to-one) 出版商模型:出版商有名稱,所在城市以及email。 書籍模型: 書籍有
9.17 模型層 ORM 單表操作
alt manager pre 可選參數 正則 directory primary 管理 rim 1 創建模型 創建名為book的app,在book下的models.py中創建模型: from django.db import models # Create your m
模板匯入和繼承+模型層:單表操作
知識點: 1、web應用: -s包括兩部分:web伺服器 和 application -目前階段django專案用的web伺服器是:wsgiref + application -上線會用uwsgi + application -web伺服器(本質是socket)都實現了wsgi協議 -ws
Django之模型層,單,多表操作(二)
一:單表操作之增,刪,改 1.1:增 方式一: book_obj=Book.objects.create(title="python葵花寶典",state=True,price=100,publish="蘋果出版社",pub_date="2012-12-12") 方式二
Django 模型層之多表操作
一.建立模型 例項: 作者表: 擁有欄位:姓名(name),性別(sex),該表與書籍表之間為多對多的關係 作者詳情表: 擁有欄位:地址(addr),手機號(phone),該表與作者表之間為一對一的關係 出版社表: 擁有欄位:名字(name),地址(addr),該表與書籍表之間為一
Django模型層之多表操作
一、建立多表模型 例項: 作者表: 擁有欄位:姓名(name),性別(sex),該表與書籍表之間為多對多的關係 作者詳情表: 擁有欄位:地址(addr),手機號(phone),該表與作者表之間為一對一的關係 出版社表: 擁有欄位:名字(name),地址(addr),該表與書籍
Django之模型層,單,多表操作(一)
一:資料庫型別 資料庫主要分成兩類,關係型資料庫和非關係型資料庫,具體區別可參照部落格地址,https://blog.csdn.net/u012965373/article/details/51779361。以下個人簡單理解 1:關係型資料庫: ORM 物件關係型對映。用物件的方式儲存資
Django之模型層,單,多表操作(三)
一:多表操作之增、刪、改 1.1:增: 一對多: 方式1: publish_obj=Publish.objects.get(nid=1) book_obj=Book.objects.create(title="海爾兄弟",publi
Django之模型層-多表操作
自動 int its 數量 val foreign 編寫 ces first 多表操作 數據庫表關系 一對多:兩個表之間的關系一旦確定為一對多,必須在數據多的表中創建關聯字段 多對多:兩個表之間的關系一定確定為多對多,必須創建第三張表(關聯表) 一對一:一旦兩個表之間的關
{Django基礎六之ORM中的鎖和事務}一 鎖 二 事務
eno tip 行數 數據完整性 nbsp err access _for pre 本節目錄 一 鎖 二 事務 一 鎖 行級鎖 select_for_update(now
django基礎知識之模板:
編譯 處理 加載 res 對象 應用 基礎知識 render ont 模板介紹 作為Web框架,Django提供了模板,可以很便利的動態生成HTML 模版系統致力於表達外觀,而不是程序邏輯 模板的設計實現了業務邏輯(view)與顯示內容(template)的分離,一個