成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久

您的位置:首頁技術文章
文章詳情頁

Django模型層實現多表關系創建和多表操作

瀏覽:4日期:2024-09-03 14:03:58
目錄前言創建表關系多表數據操作 - 增刪改一對多&一對一關系 - 增刪改增加數據刪除數據修改數據多對多關系 - 增刪改增加多對多關系 - add()刪除多對多關系 - remove()修改多對多關系 - set()清空第三張表某個對象的綁定關系 - clear()多表查詢子查詢正向查詢反向查詢聯表查詢正向查詢反向查詢聚合查詢分組查詢F與Q查詢F查詢Q查詢django開啟事務前言

繼續上面一篇文章的內容,本文介紹多表操作。使用django ORM可以創建多表關系,并且也支持多張表之間的操作,以創建表關系和查詢兩部分說明django ORM的多表操作。以作者、圖書、出版社和作者信息幾張表作為案例進行說明。

創建表關系

注意:在實際開發中不推薦使用外鍵建立表關系即不使用級聯更新和級聯刪除,而是推薦使用邏輯上的外鍵關系建立表關系。

上述的四張表中,圖書和出版社這兩表的關系屬于一對多的關系,外鍵建立在查詢頻率高的一方。作者和作者詳情表屬于一對一關系,外鍵建立在查詢頻率高的一方,作者和圖書屬于多對多關系,需要第三張表存儲關系,建議將外鍵建在查詢頻率高的一方。創建表時一定要執行數據庫遷移命令哦~

創建表關系時可以先將表模型創建出來,然后再添加外鍵字段,另外在使用django ORM創建外鍵關系時,關聯的外鍵字段會自動在字段后加_id,表與表之間的關系默認以主鍵作為關聯字段。另外在創建表關系時,不建議使用實質的外鍵進行關聯,而是通過使用邏輯上的關系來指定表關系。

class Book(models.Model): name = models.CharField(max_length=60, verbose_name=’圖書名’) # 浮點數字段,max_digits表示數字共8位, decimal_place表示小數點占2位 price = models.DecimalField(max_digits=8, decimal_places=2, verbose_name=’圖書價格’) inventory_num = models.IntegerField(verbose_name=’庫存數量’) sell_num = models.IntegerField(verbose_name=’賣出數量’) # 一對多關系外鍵字段創建使用 ForeigenKey(to=’表名’),默認關聯主鍵字段, db_constraint=Flase表示不建立實質的外鍵關系,只是邏輯上的關系 publish = models.ForeignKey(to=’Publish’, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name=’外鍵關聯出版社’) # 多對多關系,使用ManyToManyField(to=’表名’),author是一個虛擬的字段,主要是用來告訴ORM,書籍和作者是多對多的關系,而且ORM會自動創建多對多關系的第三張 author = models.ManyToManyField(to=’Author’, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name=’外鍵關聯作者’)class Publish(models.Model): name = models.CharField(max_length=12, verbose_name=’出版社名稱’)class Author(models.Model): name = models.CharField(max_length=10, verbose_name=’作者名稱’) # 一對一關系使用OneToOneField(to=’表名’) author_detail = models.OneToOneField(to=’AuthorDetail’, on_delete=models.DO_NOTHING, db_constraint=False, verbose_name=’外間關聯作者詳情’)class AuthorDetail(models.Model): age = models.IntegerField(verbose_name=’年齡’) phone = models.CharField(max_length=11, verbose_name=’手機號’)

另外還需補充一點,多對多的表關系共有三種創建方式,分別是全自動創建、半自動創建和全手動創建:

# 全自動創建 - ManyToManyField,一般這種方式可以滿足需求’’’使用全自動創建多對多關系的優點就是無需手動創建第三張表,非常方便,django ORM直接提供操作第三張表關系的方法缺點就是無法擴展第三張關系表’’’class Book(models.Model): name = models.CharField(max_length=32) authors = models.ManyToManyField(to=’Author’) class Author(models.Model): name = models.CharField(max_length=32) # 純手動創建 - ForeignKey手動創建第三張表’’’第三張表完全取決于手動的擴展,但是需要寫的代碼較多,而且無法使用ORM提供的簡單方法’’’class Book(models.Model): name = models.CharField(max_length=32) class Author(models.Model): name = models.CharField(max_length=32) class Book2Author(models.Model): book_id = models.ForeignKey(to=’Book’) author_id = models.ForeignKey(to=’Author’) # 半自動創建,通過ManyToManyField的參數控制第三張表class Book(models.Model): name = models.CharField(max_length=32) authors = models.ManyToManyField(to=’Author’, # 告訴ORM不需要自動幫忙創建第三張關系表through=’Book2Author’, # 告訴ORM第三張關系表對應的表的外鍵字段through_fields=(’book’,’author’) # 通過哪兩個字段關聯表,當前在哪張表,就先寫哪個表的關聯字段 )class Author(models.Model): name = models.CharField(max_length=32) class Book2Author(models.Model): book = models.ForeignKey(to=’Book’) author = models.ForeignKey(to=’Author’)多表數據操作 - 增刪改

首先介紹多表操作的增刪改操作,因為多表的查詢數據操作稍微麻煩一點,單獨另外開小灶。

一對多&一對一關系 - 增刪改

一對一和一對多的增刪改操作基本是一致的。

增加數據

增加數據有兩種方式,一種方式是通過實際字段來添加,另一種方式是通過虛擬字段對象賦值添加。

# 方式1:通過實際字段book_obj = models.Book.objects.create(name=’哈利波特’, price=10.2, publish_id=1)# 方式2,先獲取出版社對象,再將書籍和出版社通過出版社對象進行關聯publis_obj = models.Publish.objects.filter(pk=1).first()book_obj = models.Book.objects.create(name=’哈利波特’, price=10.2, publish=publis_obj)刪除數據

需要說明一點,在實際項目開發中刪除數據并不是真的刪除了,而是使用一個布爾類型的字段標識該數據是否刪除。刪除數據的時候如果不指定on_delete=models.DO_NOTHING默認是級聯更新級聯刪除的。

models.Publish.objects.filter(pk=1).delete()修改數據

修改數據同增加數據一樣有兩種方式。

# 方式1models.Book.objects.filter(pk=1).update(publish_id=1)# 方式2pub_obj = models.Publish.objects.filter(pk=2).first()models.Book.objects.filter(pk=1).update(publish=pub_obj)多對多關系 - 增刪改

首先需要明確的是,多對多的增刪改是在操作第三張關系表,但是第三張關系表是django自動創建的,如何通過代碼進入第三張表呢?多對多的外鍵關系被建在book表,多對多的外鍵字段是author字段,因此通過book_obj.author即可操作第三張表了。對于django自動創建的第三張表的多對多關系,django提供了額外的方法對數據進行操作。

增加多對多關系 - add()

add()方法給第三張關系表添加數據,括號內既可以傳數字也可以傳對象,并且都支持多個同時操作。

# 方式1,直接添加id值book_obj = models.Book.objects.filter(pk=1).first()book_obj.author.add(1) # 增加 1 1記錄,即id為1的書綁定id為1的作者book_obj.author.add(2, 3) # 增加兩條記錄,1 2 和 1 3# 方式2,通過對象添加關系book_obj = models.Book.objects.filter(pk=2).first()author_obj1 = models.Author.objects.filter(pk=1).first()author_obj2 = models.Author.objects.filter(pk=2).first()author_obj3 = models.Author.objects.filter(pk=3).first()book_obj.author.add(author_obj1) # 增加1條記錄book_obj.author.add(author_obj2, author_obj3) # 增加2條刪除多對多關系 - remove()

remove()方法用來為第三張表刪除數據,同樣的,括號內既可以傳數字也可以傳對象,并且支持多條數據同時操作。

# 方式1:直接刪除值book_obj = models.Book.objects.filter(pk=1).first()book_obj.author.remove(2) # 刪除book_id為1和author_id都為2的記錄book_obj.authors.remove(1, 3) # 刪除多條# 方式2:通過對象刪除author_obj1 = models.Author.objects.filter(pk=2).first()author_obj2 = models.Author.objects.filter(pk=3).first()book_obj.authors.remove(author_obj1, author_obj2)修改多對多關系 - set()

set()方法用來修改第三張表,該方法是一個覆蓋操作,用新的關系覆蓋之前的關系,該方法的參數必須是一個列表或者元組,指出數字或對象,也支持多條數據同時操作。

# 方式1:直接通過值進行修改book_obj = models.Book.objects.filter(pk=1).first()book_obj.author.set([2]) # 將book_id為1對應的author_id修改為2book_obj.authors.set([1, 2]) # 將書的作者設置為id=1 和id=2的作者# 方式2:通過對象進行修改author_obj2 = models.Author.objects.filter(pk=2).first()author_obj3 = models.Author.objects.filter(pk=3).first()book_obj.authors.set([author_obj2, author_obj3])清空第三張表某個對象的綁定關系 - clear()

clear()方法會清空第三張關系表中某個對象的綁定關系。

book_obj = models.Book.objects.filter(pk=1).first()book_obj.author.clear()多表查詢

在進行多表查詢操作前,需要了解一個概念,什么是正向查詢和反向查詢。

正向查詢:外鍵在哪個表中,查詢關聯的表就是正向查詢,比如通過書籍查詢出版社; 反向查詢:被關聯的表查外鍵字段所在的表就是反向查詢,比如通過出版社查詢書籍。子查詢

如果查詢比較復雜時可以采用子查詢的方式,子查詢就是分步驟查詢的意思,先查詢得到的結果作為后查詢的條件。

正向查詢

正向查詢按字段,如果有多個結果需要外鍵字段.all(),那么怎么判斷查詢的結果有多個呢?如果在不加.all()的情況下得到的結果是應用名.模型名.None比如first.Author.None這種情況下說明ORM 語句沒有錯誤,只是查詢到的結果有多個,就需要加.all()。當查詢結果只有一個時得到的是一個模型對象,如果為多個就是QuerySet對象。

# 一對多關系查詢:查詢書籍主鍵為1的書籍由哪個出版社出版book_obj = models.Book.objects.filter(pk=1).first()res = book_obj.publish # Publish object (1)print(res.name)# 多對多關系查詢:查詢數據主鍵為1的作者book_obj = models.Book.objects.filter(pk=1).first()res = book_obj.author # first.Author.None,說明結果有多個res_many = book_obj.author.all() # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]> # 一對一關系查詢:查詢作者lili的年齡author_obj = models.Author.objects.filter(name=’lili’).first()res = author_obj.author_detailprint(res.phone)反向查詢

反向查詢如果是一對一的話是表名小寫,如果是一對多或者多對多時反向查詢是表明小寫——set,另外如果有多個結果需要在表明小寫后再加_set.all(),判斷結果是否有多個的方法與正向查詢相同。當查詢結果只有一個時得到的是一個模型對象,如果為多個就是QuerySet對象。

# 一對多關系查詢,查詢出版社是東方出版社出版的書publish_obj = models.Publish.objects.filter(name=’東方’).first()res = publish_obj.book_set.all() # <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]># 多對多關系查詢,查詢作者是lili寫過的書author_obj = models.Author.objects.filter(name=’lili’).first()res = author_obj.book_set # first.Book.None,說明有多個結果res_many = author_obj.book_set.all()print(res_many) # <QuerySet [<Book: Book object (1)>]># 一對一關系查詢,查詢手機號是119的作者author_detail_obj = models.AuthorDetail.objects.filter(phone=’119’).first()res = author_detail_obj.authorprint(res.name)聯表查詢

聯表查詢就是像MySQ里面SQL語句的聯表查詢一樣,只不過在django的ORM里面使用基于雙下劃線聯表查詢(跨表查詢)。聯表查詢的可以使用一行代碼查詢結果,聯表查詢也遵循正反向關系。

正向查詢

# 一對多關系查詢:查詢書籍主鍵為1的出版社名稱和書名# 首先獲取書籍對象,書籍是查詢publish的基表,因此獲取書名直接values(’names’)即可,而出版社的名字是通過外鍵字段跳到出版社的表中農,需要通過__找到需要的字段值res = models.Book.objects.filter(pk=1).values(’name’, ’publish__name’) # <QuerySet [{’name’: ’哈利波特’, ’publish__name’: ’東方’}]># 多對多關系查詢,查詢書籍主鍵為1的作者姓名res = models.Book.objects.filter(pk=1).values(’author__name’) # <QuerySet [{’author__name’: ’lili’}, {’author__name’: ’nana’}]># 一對一關系查詢,查詢lili的手機號和姓名res = models.Author.objects.filter(name=’lili’).values(’name’, ’author_detail__phone’).first()print(res.get(’name’), res.get(’author_detail__phone’))反向查詢

# 一對多關系查詢:查詢數據主鍵為1的出版社名稱和書的名字res = models.Publish.objects.filter(book__id=1).values(’name’, ’book__name’) # <QuerySet [{’name’: ’東方’, ’book__name’: ’哈利波特’}]># 多對多關系查詢:查詢書籍主鍵為1的作者姓名和書名res = models.Author.objects.filter(book__id=1).values(’name’, ’book__name’) # <QuerySet [{’name’: ’lili’, ’book__name’: ’哈利波特’}, {’name’: ’nana’, ’book__name’: ’哈利波特’}]># 一對一關系查詢:查詢作者id是1作者的姓名和手機號res = models.AuthorDetail.objects.filter(author__id=1).values(’author__name’, ’phone’) # <QuerySet [{’author__name’: ’lili’, ’phone’: ’119’}]># 綜合大查詢:查詢書籍主鍵是1的作者的手機號,首先獲取書籍對象,書籍關聯了作者表,作者表又關聯了作者詳情表 res = models.Book.objects.filter(pk=1).values(’author__author_detail__phone’) # <QuerySet [{’author__author_detail__phone’: ’119’}, {’author__author_detail__phone’: ’120’}]>聚合查詢

聚合查詢通常情況下是配合分組一起使用的,聚合查詢就是用一些統計工具,比如最大值,最小值,平均值等,聚合函數的導入方式from django.db.models import Max, Min, Sum, Count, Avg,如果在不分組的情況下使用聚合函數需要在aggregate()方法內使用。

from django.db.models import Min,Max,Sum,Count,Avg# 統計書的平均價格res = models.Book.objects.aggregate(Avg(’price’))print(res)# 可以將這些聚合函數同時使用res = models.Book.objects.aggregate(Max(’price’),Sum(’price’),Count(’pk’))print(res)分組查詢

聚合函數通常和分組一起使用,分組查詢的方法是annotate,默認以models.分組依據作為分組依據,即表的主鍵進行分組,如果annotate()方法前面出現了values()那么就會按照values中指定的值進行分組。分組查詢支持__跨表查詢。

from django.db.models import Sum, Max, Min, Avg, Count# 1.統計每本書的作者個數res = models.Book.objects.annotate(author_num=Count(’author’)).values(’name’, ’author_num’) # author_num是自己定義的字段用來存儲統計出來的每本書對應的作者個數,暫時存為表中的字段# 2.統計每個出版社賣的最便宜的書的價格res = models.Publish.objects.annotate(min_price=Min(’book__price’)).values(’name’, ’min_price’)# 3.統計不止一個作者的圖書# 先按照圖書分組,算出每本書的作者數量,再過濾出作者數量大于1的數據res = models.Book.objects.annotate(author_num=Count(’author’)).filter(author_num__gt=1).values(’name’, ’author_num’)# 4.查詢每個作者出版書的總價格res = models.Author.objects.annotate(sum_price=Sum(’book__price’)).values(’name’, ’sum_price’)F與Q查詢F查詢

F查詢可以獲得表中某個字段的數據值,尤其適合表中兩個字段之間的比較運算,在操作字符類型的數據時,F不能直接做字符串的拼接,需要借助Concat和Value。

from django.db.models import F# 1.查詢賣出數量大于庫存數量的書籍res = models.Book.objects.filter(sell_num__gt=F(’inventory_num’))# 將所有書籍的價格提升20元res = models.Book.objects.update(price=F(’price’)+20)

F查詢對于字符串的操作需要借助Concat和Value兩個方法:

# 將所有書的名稱后面加上爆款兩個字from django.db.models.functions import Concatfrom django.db.models import F, Valuemodels.Book.objects.update(name=Concat(F(’name’),Value(’爆款’)))Q查詢

使用filter()進行條件過濾時,采用的是邏輯與and的操作,如果想要將多個篩選條件更改為or或者not的關系則需要借助Q查詢。在Q查詢中|表示or的關系,~表示not的關系。

import django.db.models import Q# 查詢賣出數量大于100或者價格小于20的書籍res = models.Book.objects.filter(~Q(sell_num__gt=100) | Q(price__lt=20))

另外Q查詢還有另一個比較高級的用法,就是可以將查詢條件的左邊也變成字符串的形式。

# 先產生一個Q的實例q = Q()# 修改q的連接條件的關系q.connector = ’or’q.children.append((’sell_num__gt’,100))q.children.append((’price__lt’,200))res = models.Book.objects.filter(q)# filter的條件是Q實例化產生的對象,每個條件默認還是and關系,可以修改print(res)django開啟事務

MySQL為了保證數據的安全有一個事務的機制,django既然能夠連接MySQL那么django就可以支持MySQL的事務機制。下述代碼就是在django中開啟事務:

from django.db import transactiontry: with transaction.atomic(): # 在with代碼快內書寫的所有orm操作都屬于同一個事務...except Exception as e: print(r)...

到此這篇關于Django模型層實現多表關系創建和多表操作的文章就介紹到這了,更多相關Django 多表操作內容請搜索好吧啦網以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持好吧啦網!

標簽: Django
相關文章:
成人在线亚洲_国产日韩视频一区二区三区_久久久国产精品_99国内精品久久久久久久
国产91丝袜在线播放0| 国产精品123区| 日本网站在线观看一区二区三区| 亚洲高清视频一区| 国产精品无圣光一区二区| 成人激情动漫在线观看| 91精品国产品国语在线不卡| 另类小说图片综合网| 久久精品欧美| 亚洲一区二区三区视频在线播放| 伊人狠狠色j香婷婷综合| 久久久久9999亚洲精品| 国产成人免费视频精品含羞草妖精 | 国产精品国产三级国产aⅴ无密码| 白白色亚洲国产精品| 欧美一级专区免费大片| 国产精品一区不卡| 日韩视频免费观看高清在线视频| 国产精品综合二区| 91精品国产色综合久久ai换脸| 国产一区二区h| 欧美一区二区三区性视频| 国产麻豆视频一区二区| 91精品国产欧美一区二区成人| 国产精一品亚洲二区在线视频| 911精品国产一区二区在线| 国产一区欧美日韩| 5月丁香婷婷综合| 国产乱对白刺激视频不卡| 欧美亚洲动漫精品| 美女一区二区三区在线观看| 欧美日韩一区高清| 国产美女视频91| 日韩精品一区二区三区swag| 99精品久久久久久| 欧美国产日韩亚洲一区| 在线播放豆国产99亚洲| 亚洲一区二区三区在线看| 国产久一道中文一区| 天使萌一区二区三区免费观看| 久久久久高清| 毛片一区二区三区| 91精品欧美久久久久久动漫| 成人av在线看| 国产午夜精品久久久久久免费视 | 亚洲精品一卡二卡| 噜噜噜91成人网| 美脚の诱脚舐め脚责91| 欧美一二三区在线| www.日韩大片| 国产精品女同互慰在线看| 亚洲三级观看| 午夜精品123| 欧美日韩一区二区不卡| 成人综合婷婷国产精品久久| 国产视频一区二区在线| 国产精品hd| 亚洲国产色一区| 欧美人与z0zoxxxx视频| 成人的网站免费观看| 欧美韩日一区二区三区| 中文精品视频| 毛片基地黄久久久久久天堂| 精品国产亚洲在线| 亚洲午夜激情在线| 亚洲成人精品影院| 欧美日韩高清一区| 91麻豆福利精品推荐| 亚洲日穴在线视频| 日本精品一级二级| 不卡的看片网站| 国产精品青草久久| 一本久久a久久精品亚洲| 国产米奇在线777精品观看| 久久久久久久久蜜桃| 一区二区三区精品视频在线观看 | 美女视频黄a大片欧美| 久久综合视频网| 中国女人久久久| 国产精品一区在线| 综合在线观看色| 在线播放一区二区三区| 精品69视频一区二区三区Q| 免费的国产精品| 久久精品在线观看| 久久激情久久| 成人黄色777网| 亚洲一区中文日韩| 91精品国产aⅴ一区二区| 影音欧美亚洲| 麻豆91小视频| 国产无人区一区二区三区| 久久国产精品免费一区| 丰满岳乱妇一区二区三区| 亚洲色图色小说| 欧美电影一区二区| 99成人在线| 国产激情一区二区三区| 亚洲欧美综合网| 欧美在线播放高清精品| 欧美日韩精品免费看| 日本欧美一区二区三区乱码| 久久精品视频网| 欧美亚洲动漫精品| 亚洲人www| 成人免费毛片高清视频| 午夜一区二区三区在线观看| 26uuu亚洲综合色| 一本一道综合狠狠老| 午夜精品一区二区在线观看| 国产综合久久久久影院| 亚洲精品视频自拍| 亚洲精品一区二区三区福利| 色婷婷综合中文久久一本| 欧美69视频| 国产精选一区二区三区| 亚洲不卡av一区二区三区| 久久久久亚洲蜜桃| 欧美亚洲综合一区| 亚洲免费大片| 99麻豆久久久国产精品免费| 美女视频一区在线观看| 一区二区三区在线视频观看58| 精品少妇一区二区三区日产乱码 | 一区二区三区**美女毛片| 久久久久国产精品麻豆| 91精品办公室少妇高潮对白| 国产一区高清视频| 成人精品电影在线观看| 免费成人小视频| 亚洲一区二区三区四区不卡| 国产午夜精品一区二区| 91精品国产一区二区三区蜜臀| 看欧美日韩国产| 一本色道久久综合亚洲精品婷婷| 99精品久久99久久久久| 国产呦精品一区二区三区网站| 午夜精品久久久久久久| 中文字幕高清不卡| 亚洲精品一区二区三区四区高清| 欧美日韩久久不卡| 久久国产精品久久精品国产| 亚洲精品欧美| 欧美精品二区| a在线播放不卡| 精品一区二区三区欧美| 天天色天天操综合| 亚洲人成精品久久久久久| 久久精品亚洲一区二区三区浴池 | 国产精品色一区二区三区| 日韩精品一区二区三区视频在线观看 | 伊人婷婷欧美激情| 中文欧美字幕免费| 久久亚洲捆绑美女| 日韩欧美综合在线| 欧美人与z0zoxxxx视频| 欧美午夜宅男影院| 久久午夜影视| 久久国产日韩| 鲁大师成人一区二区三区| 99成人在线| 国产欧美日韩在线播放| 亚洲高清自拍| 亚洲图片在线观看| 狠狠综合久久| 黄色成人在线网址| 狠色狠色综合久久| 狠狠久久婷婷| 国色天香一区二区| 国产精品二区在线| 一区在线视频观看| 亚洲二区精品| 亚洲黄色视屏| 中文精品在线| 国产日韩亚洲| 国产精品区免费视频| 国产精品呻吟| 久久久7777| 一本色道久久综合亚洲91| 看欧美日韩国产| 在线精品观看国产| 欧美精品日韩精品| 欧美一级二级在线观看| 精品国一区二区三区| 亚洲精品一区二区三区99| 久久久久青草大香线综合精品| 久久久久久99久久久精品网站| 欧美国产成人精品| 一区二区中文视频| 亚洲欧美日韩国产一区二区三区| 亚洲男人天堂一区| 亚洲午夜三级在线| 手机精品视频在线观看| 日av在线不卡| 国产伦精品一区二区三区在线观看| 国产精品一区二区无线| va亚洲va日韩不卡在线观看| 欧美一区91| 一区二区三区导航| 久久一区中文字幕|