您好,登錄后才能下訂單哦!
本篇文章為大家展示了如何進(jìn)行ORM多表操作,內(nèi)容簡明扼要并且容易理解,絕對能使你眼前一亮,通過這篇文章的詳細(xì)介紹希望你能有所收獲。
from django.db import models # Create your models here. class AuthorDtail(models.Model): nid = models.AutoField(primary_key=True) birthday = models.DateField() telephone = models.BigIntegerField() addr = models.CharField(max_length=64) class Author(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() # OneToOneField可以建立在兩個模型中的任意一個 authorDetail = models.OneToOneField(to="AuthorDtail", to_field="nid", on_delete=models.CASCADE) class Publish(models.Model): nid = models.AutoField(primary_key=True) name = models.CharField(max_length=32) city = models.CharField(max_length=32) email = models.EmailField() class Book(models.Model): nid = models.AutoField(primary_key=True) title = models.CharField(max_length=32) publishDate = models.DateField() price = models.DecimalField(max_digits=9,decimal_places=2) # 與Publish建立一對多的關(guān)系,外鍵字段建立在多的一方 publish = models.ForeignKey(to="Publish", to_field="nid", on_delete=models.CASCADE) # 多對多,ManyToManyField可以建在兩個模型中的任意一個,自動創(chuàng)建第三張表 authors = models.ManyToManyField(to="Author")
MySQL查看建表語句
CREATE TABLE `app1_authordetail` ( `nid` int(11) NOT NULL AUTO_INCREMENT, `birthday` date NOT NULL, `telephone` bigint(20) NOT NULL, `addr` varchar(64) NOT NULL, PRIMARY KEY (`nid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; #UNIQUE KEY `authorDetail_id` (`authorDetail_id`),這是OneToOneField創(chuàng)建的。 CREATE TABLE `app1_author` ( `nid` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `age` int(11) NOT NULL, `authorDetail_id` int(11) NOT NULL, PRIMARY KEY (`nid`), UNIQUE KEY `authorDetail_id` (`authorDetail_id`), CONSTRAINT `app1_author_authorDetail_id_d894fd2a_fk_app1_authordetail_nid` FOREIGN KEY (`authorDetail_id`) REFERENCES `app1_authordetail` (`nid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `app1_publish` ( `nid` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(32) NOT NULL, `city` varchar(32) NOT NULL, `email` varchar(254) NOT NULL, PRIMARY KEY (`nid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `app1_book` ( `nid` int(11) NOT NULL AUTO_INCREMENT, `title` varchar(32) NOT NULL, `publishDate` date NOT NULL, `price` decimal(9,2) NOT NULL, `publish_id` int(11) NOT NULL, PRIMARY KEY (`nid`), KEY `app1_book_publish_id_e41ee7e4` (`publish_id`), CONSTRAINT `app1_book_publish_id_e41ee7e4_fk_app1_publish_nid` FOREIGN KEY (`publish_id`) REFERENCES `app1_publish` (`nid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; #ManyToManyField創(chuàng)建的第三方表 CREATE TABLE `app1_book_authors` ( `id` int(11) NOT NULL AUTO_INCREMENT, `book_id` int(11) NOT NULL, `author_id` int(11) NOT NULL, PRIMARY KEY (`id`), UNIQUE KEY `app1_book_authors_book_id_author_id_ce887e61_uniq` (`book_id`,`author_id`), KEY `app1_book_authors_author_id_89b9ee26_fk_app1_author_nid` (`author_id`), CONSTRAINT `app1_book_authors_author_id_89b9ee26_fk_app1_author_nid` FOREIGN KEY (`author_id`) REFERENCES `app1_author` (`nid`), CONSTRAINT `app1_book_authors_book_id_75b281cd_fk_app1_book_nid` FOREIGN KEY (`book_id`) REFERENCES `app1_book` (`nid`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
1.表的名稱是app_modelName,是根據(jù)模型中的元數(shù)據(jù)自動生成的,也可以重寫為別的名稱。 2.如果沒有定義AutoField(),默認(rèn)會創(chuàng)建id字段,為主鍵。 3.對于外鍵字段,Django會在字段上添加"_id"來設(shè)置列名。 4.Django會根據(jù)settings中指定的數(shù)據(jù)庫類型來使用相應(yīng)的SQL語句。 5.要在INSTALL_APPS中設(shè)置models.py所在的應(yīng)用名稱 6.外鍵字段 ForeignKey 有一個 null=True 的設(shè)置(它允許外鍵接受空值 NULL),你可以賦給它空值 None 。
from django.shortcuts import render from app1.models import * def index(request): # 注意:這里一定要是一個model對象,不能是queryset對象 # 方式一:設(shè)置publish,是一個Model對象。 publish_obj = Publish.objects.get(nid=1) aa_book_obj = Book.objects.create(title="AA_title",publishDate="2012-12-12",price=100,publish=publish_obj) # 方式二:設(shè)置publish_id bb_book_obj = Book.objects.create(title="BB_title", publishDate="2012-12-12", price=100, publish_id=2) print(aa_book_obj.title) print(aa_book_obj.publish.name) print(bb_book_obj.title) print(bb_book_obj.publish.name) # 這里關(guān)鍵在于publish與publish_id的區(qū)別。 # 可以發(fā)現(xiàn), # publish是一個對象,可以通過publish調(diào)用相應(yīng)Publish表中的字段數(shù)據(jù) # publish_id只是Book表中的一個字段值 print(bb_book_obj.publish.nid) print(bb_book_obj.publish_id) return render(request, "index.html")
查詢title為AA_title的出版社郵箱 book_obj=Book.objects.filter(title="AA_title").first() print(book_obj.publish.email)
from django.shortcuts import render from app1.models import * def index(request): # 綁定多對多關(guān)系 cc_book_obj = Book.objects.create(title="CC_title",publishDate="2018-12-12",price=120,publish_id=1) vita = Author.objects.get(name="vita") lili = Author.objects.get(name="lili") # 方式一:add-author對象 cc_book_obj.authors.add(vita,lili) # 方式二:add-author_id dd_book_obj = Book.objects.create(title="DD_title",publishDate="2018-12-12",price=120,publish_id=1) dd_book_obj.authors.add(1,2) # 方式三:add-*[1,2,3] ee_book_obj = Book.objects.create(title="EE_title", publishDate="2018-12-12", price=120, publish_id=1) ee_book_obj.authors.add(*[1,2]) return render(request, "index.html")
from django.shortcuts import render from app1.models import * def index(request): ee_book_obj = Book.objects.filter(title="EE_title").first() # 關(guān)鍵點:ee_book_obj.authors.all() # 與本書關(guān)聯(lián)的所有作者信息集合,是queryset對象 # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]> print(ee_book_obj.authors.all()) return render(request, "index.html")
book_obj.authors.remove() # 將某個特定的對象從被關(guān)聯(lián)對象集合中去除。 ====== book_obj.authors.remove(*[]) book_obj.authors.clear() #清空被關(guān)聯(lián)對象集合 book_obj.authors.set() #先清空再設(shè)置
from django.shortcuts import render from app1.models import * def index(request): vita = Author.objects.filter(name="vita").first() aa_book_obj = Book.objects.filter(title="CC_title").first() # 方式一:remove-author對象 aa_book_obj.authors.remove(vita) # 方式二:remove-author的nid aa_book_obj.authors.remove(2) bb_book_obj = Book.objects.filter(title="DD_title").first() # 方式三:remove-*[1,2] bb_book_obj.authors.remove(*[1,2]) return render(request, "index.html")
1 基于對象查詢 2 基于雙下劃線查詢 3 聚合和分組查詢 4 F 與 Q查詢
一對多關(guān)系中,models.ForeignKey設(shè)置在book中, 根據(jù)book表查詢author信息,是正向查詢 根據(jù)author表查詢book信息,是反向查詢 多對多關(guān)系中,models.ManyToMany設(shè)置在book表中, 根據(jù)book表查詢author信息,是正向查詢 根據(jù)author表查詢book信息,是反向查詢 一對一關(guān)系中,models.OneToOne設(shè)置在author表中, 根據(jù)author表查詢authoDetail信息,是正向查詢 根據(jù)authorDetail表查詢quthor信息,是反向查詢 守則: 正想查詢按字段 反向查詢按表名 詳解: 正向查詢按字段,models.py中設(shè)置的關(guān)聯(lián)字段,即Author類中的authorDetail,Book類中的publish和author。 (一對多,多對多)反向查詢按表名小寫_set----因為是多個數(shù)據(jù),所以使用set,集合之意。 (一對一)反向查詢按表名小寫----因為只有一條對應(yīng)數(shù)據(jù),所以無set。
守則: 正想查詢按字段 反向查詢按表名 詳解: 正向查詢按字段,models.py中設(shè)置的關(guān)聯(lián)字段,即Author類中的authorDetail,Book類中的publish和author。 (一對多,多對多)反向查詢按表名小寫_set----因為是多個數(shù)據(jù),所以使用set,集合之意。 (一對一)反向查詢按表名小寫----因為只有一條對應(yīng)數(shù)據(jù),所以無set。
from django.shortcuts import render from app1.models import * def index(request): # 一對多的正向查詢:查詢?nèi)龂萘x這本書的出版社名字 # 一本書只對應(yīng)一個出版社,返回值是一個model對象 publish_obj = Book.objects.filter(title="SanGuo").first().publish print(publish_obj) # Publish object (1) print(publish_obj.name) # AA出版社 # SQL語句: # 一對多的反向查詢:查詢 AA_出版社 出版過的書籍名稱 # 一個出版社對應(yīng)多本書,返回值是一個queryset集合 book_list = Publish.objects.filter(name="AA_publish").first().book_set.all() print(book_list) # <QuerySet [<Book: Book object (7)>, <Book: Book object (9)>, <Book: Book object (10)>, <Book: Book object (11)>]> # SQL語句: return render(request, "index.html")
from django.shortcuts import render from app1.models import * def index(request): # 多對多正向查詢:查詢Sanguo這本書的所有作者名字 # 書和作者是多對多關(guān)系,返回值是queryset集合。 # <QuerySet [<Author: Author object (1)>, <Author: Author object (2)>]> author_list = Book.objects.filter(title="SanGuo").first().authors.all() print(author_list) # 多對多反向查詢:查詢vita出版過的所有書籍名稱 # 書和作者是多對多關(guān)系,返回值是queryset集合。 # <QuerySet [<Book: Book object (7)>, <Book: Book object (8)>, <Book: Book object (9)>, <Book: Book object (10)>, <Book: Book object (11)>]> book_list = Author.objects.filter(name="vita").first().book_set.all() print(book_list) return render(request, "index.html")
from django.shortcuts import render from app1.models import * def index(request): # 一對一的正向查詢:查詢vita的手機(jī)號 # 一對一關(guān)系,返回值是model對象 # AuthorDetail object (1) author_detail_obj = Author.objects.filter(name="vita").first().authorDetail print(author_detail_obj) # 一對一的反向查詢:查詢手機(jī)號為112233的作者 # 一對一關(guān)系,返回值是model對象 # Author object (1) author_obj = AuthorDetail.objects.filter(telephone="112233").first().author print(author_obj) return render(request, "index.html")
守則: 正想查詢按字段 反向查詢按表名
from django.shortcuts import render from app1.models import * def index(request): # 一對多查詢:查詢SanGuo這本書的出版社名字 # 返回值是queryset對象 # 方式一正向查詢: ret = Book.objects.filter(title="SanGuo").values("publish__name") print(ret) # <QuerySet [{'publish__name': 'AA_publish'}]> # 方式二反向查詢: ret2 = Publish.objects.filter(book__title="SanGuo").values("name") print(ret2) # <QuerySet [{'name': 'AA_publish'}]> # 一對多查詢:查詢 AA_publish出版社出版的書籍名稱 # 返回值是queryset對象 # 方式一正向查詢: ret3 = Publish.objects.filter(name="AA_publish").values("book__title") print(ret3) # <QuerySet [{'book__title': 'SanGuo'}, {'book__title': 'HongLou'}, {'book__title': 'XiYou'}, {'book__title': 'XiaoWangZi'}]> # 方式二反向查詢: ret4 = Book.objects.filter(publish__name="AA_publish").values("title") print(ret4) # <QuerySet [{'title': 'SanGuo'}, {'title': 'HongLou'}, {'title': 'XiYou'}, {'title': 'XiaoWangZi'}]> return render(request, "index.html")
from django.shortcuts import render from app1.models import * def index(request): # 多對多查詢:查詢SanGuo這本書的所有作者的名字 # 返回值:queryset對象 # 方式一:正向查詢 ret1 = Book.objects.filter(title="SanGuo").values("authors__name") print(ret1) # <QuerySet [{'authors__name': 'vita'}, {'authors__name': 'lili'}]> # 方式二:反向查詢 ret2 = Author.objects.filter(book__title="SanGuo").values("name") print(ret2) # <QuerySet [{'name': 'vita'}, {'name': 'lili'}]> return render(request, "index.html")
from django.shortcuts import render from app1.models import * def index(request): # 一對一查詢:查詢vita的手機(jī)號 # 返回值queryset對象 # 方式一:正向查詢 ret1 = Author.objects.filter(name="vita").values("authorDetail__telephone") print(ret1) # <QuerySet [{'authorDetail__telephone': 112233}]> # 方式二:反向查詢 ret2 = AuthorDetail.objects.filter(author__name="vita").values("telephone") print(ret2) # <QuerySet [{'telephone': 112233}]> return render(request, "index.html")
from django.shortcuts import render from app1.models import * def index(request): # 手機(jī)號以11開頭的作者出版過的書籍名稱以及出版社的名稱 ret1 = Author.objects.filter(authorDetail__telephone__startswith="11").values("book__title","book__publish__name") print(ret1) ret2 = AuthorDetail.objects.filter(telephone__startswith="11").values("author__book__title","author__book__publish__name") print(ret2) ret3 = Book.objects.filter(authors__authorDetail__telephone__startswith="11").values("title","publish__name") print(ret3) return render(request, "index.html")
返回值是字典
from django.shortcuts import render from django.db.models import Avg,Max,Min,Count from app1.models import * def index(request): # 查詢所有書籍的平均價格 # 返回值是字典 ret = Book.objects.filter(publishDate__year=2012).aggregate(avg_price=Avg("price"),max_price=Max("price"),min_price=Min("price")) print(ret) # {'avg_price': Decimal('100.000000'), 'max_price': Decimal('100.00'), 'min_price': Decimal('100.00')} return render(request, "index.html")
# annotate分組查詢 # 單表分組查詢的ORM語法: 單表模型.objects.values("group by的字段").annotate(聚合函數(shù)("統(tǒng)計字段")) # 返回值為queryset對象 # 補(bǔ)充知識點: # # ret=Emp.objects.all() # print(ret) # select * from emp # ret=Emp.objects.values("name") # print(ret) # select name from emp # 單表下按照id分組,沒有任何意義,這里all()就包含了所有字段,包含了主鍵id,id是唯一的,按照該字段分組沒有任何意義 # Emp.objects.all().annotate(avg_salary=Avg("salary"))
from django.shortcuts import render from django.db.models import Avg,Max,Min,Count from app1.models import * def index(request): # 查詢每種價格的書的價格和數(shù)量 # ret = Book.objects.values("price").annotate(book_count = Count("nid").values("title") # 單表分組時,最后加values()是又加了一個分組字段,不是取出字段值 ret = Book.objects.values("price").annotate(book_count = Count("nid")) print(ret) # <QuerySet [{'price': Decimal('100.00'), 'book_count': 2}, {'price': Decimal('120.00'), 'book_count': 3}]> return render(request, "index.html")
from django.shortcuts import render from django.db.models import Avg,Max,Min,Count from app1.models import * def index(request): # 查詢每一個出版社的名稱以及出版的書籍?dāng)?shù) # 反向查詢 ret1 = Publish.objects.values("name").annotate(book_count=Count("book__nid")) print(ret1) # <QuerySet [{'name': 'AA_publish', 'book_count': 4}, {'name': 'BB_publish', 'book_count': 1}]> # 正向查詢 ret2 = Book.objects.values("publish__name").annotate(book_count=Count("nid")) print(ret2) # <QuerySet [{'publish__name': 'AA_publish', 'book_count': 4}, {'publish__name': 'BB_publish', 'book_count': 1}]> # 正向查詢,最后values取值 ret3 = Book.objects.values("publish__nid").annotate(book_count=Count("nid")).values("publish__name","book_count") print(ret3) # <QuerySet [{'publish__name': 'AA_publish', 'book_count': 4}, {'publish__name': 'BB_publish', 'book_count': 1}]> return render(request, "index.html")
from django.shortcuts import render from django.db.models import Avg,Max,Min,Count from app1.models import * def index(request): # 總結(jié) 跨表的分組查詢的模型: # 每一個后表模型.objects.values("pk").annotate(聚合函數(shù)(關(guān)聯(lián)表__統(tǒng)計字段)) # pk為主鍵 # 1.查詢每一個作者的名字以及出版過的書籍的最高價格 ret1 = Author.objects.values("pk").annotate(max_price = Max("book__price")).values("name","max_price") print(ret1) # 2.查詢每一個書籍的名稱以及對應(yīng)的作者數(shù) ret2 = Book.objects.values("pk").annotate(author_count = Count("authors__nid")).values("title","author_count") print(ret2) return render(request, "index.html")
from django.shortcuts import render from django.db.models import Avg,Max,Min,Count from app1.models import * def index(request): # 查詢每一個出版社的名稱以及出版社的書籍個數(shù) # 三種方式: ret1=Publish.objects.values("nid").annotate(c=Count("book__title")).values("name","email","c") print(ret1) ret2=Publish.objects.all().annotate(c=Count("book__title")).values("name","c","city") print(ret2) ret3 = Publish.objects.annotate(c=Count("book__title")).values("name", "c", "city") print(ret3) return render(request, "index.html")
from django.shortcuts import render from django.db.models import Avg,Max,Min,Count from app1.models import * def index(request): # 統(tǒng)計每一本以S開頭的書籍的作者個數(shù) ret1 = Book.objects.filter(title__startswith="S").values("pk").annotate(author_count = Count("authors__nid")).values("title","author_count") print(ret1) # 統(tǒng)計不止一個作者的圖書 ret2 = Book.objects.values("pk").annotate(author_count = Count("authors__nid")).filter(author_count__gt=1).values("title","author_count") print(ret2) return render(request, "index.html")
from django.shortcuts import render from django.db.models import F,Q from app1.models import * def index(request): # 1.F查詢,兩個字段值作比較 ret1 = Book.objects.filter(price__gt=F("publish_id")) print(ret1) # 2.F查詢與常數(shù)之間的加減乘除和取模 ret2 = Book.objects.filter(price__gt=F("publish_id")*100) print(ret2) # 3.支持批量更新 Book.objects.all().update(price=F("price")+30) return render(request, "index.html")
from django.shortcuts import render from django.db.models import F,Q from app1.models import * def index(request): # 1.Q查詢可以用于“或”查詢,filter()方法是“and”查詢 ret1 =Book.objects.filter(Q(authors__name="vita")|Q(authors__name="lili")) print(ret1) # 2.可以組合&和|以及~(取反) # 作者名是vita,age!=23 ret2 = Book.objects.filter(Q(authors__name="vita")&~Q(authors__age=23)) print(ret2) # 3.查詢函數(shù)可以混合使用Q對象和關(guān)鍵字參數(shù)。關(guān)鍵字參數(shù)要放在最后面 ret3 = Book.objects.filter(Q(authors__age=23)|Q(publishDate__year=2012),title__startswith="S") print(ret3) return render(request, "index.html")
上述內(nèi)容就是如何進(jìn)行ORM多表操作,你們學(xué)到知識或技能了嗎?如果還想學(xué)到更多技能或者豐富自己的知識儲備,歡迎關(guān)注億速云行業(yè)資訊頻道。
免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點不代表本網(wǎng)站立場,如果涉及侵權(quán)請聯(lián)系站長郵箱:is@yisu.com進(jìn)行舉報,并提供相關(guān)證據(jù),一經(jīng)查實,將立刻刪除涉嫌侵權(quán)內(nèi)容。