Django之ORM跨表操作
models.py文件內容:
from django.db import models # Create your models here. class Book(models.Model): title=models.CharField(max_length=32) price=models.DecimalField(max_digits=6,decimal_places=2) create_time=models.DateField() memo=models.CharField(max_length=32,default="") publish=models.ForeignKey(to="Publish",default=1) #定義一對多關系,會在book表添加publish_id字段 author=models.ManyToManyField("Author") #定義多對多關系,會專門生成一張book和author的關系表 def __str__(self): return self.title class Publish(models.Model): name=models.CharField(max_length=32) email=models.CharField(max_length=32) class Author(models.Model): name=models.CharField(max_length=32) def __str__(self):return self.name
#執行下面python語句生成相關表
python3 manage.py makemigrations python3 manage.py migrate
添加數據後各個表數據如下:
二、基於對象的跨表查詢
1、一對一關系
(1)查詢wang的手機號(反向查詢,按表名小寫)
obj = Author.objects.filter(name="wang").first() # 得到name="wang"的作者的對象 print(obj.authordetail.tel) # obj.authordetail表名得到作者對應的詳細信息對象,再 .tel得到結果 18971232312
(2)查詢手機號為13451222125的作者的名字 (正向查詢,按字段)
obj = AuthorDetail.objects.filter(tel="13451222125").first() # 得到tel="13451222125"的作者詳細信息的對象 print(obj.author.name) # obj.author字段得到作者對象,再 .name得到結果 li
2、一對多關系
(1)查詢id=15的書籍的出版社的名稱(正向查詢,按字段)
book_obj = Book.objects.filter(id=15).first() #得到id=15的數的對象 print(book_obj.publish.name) # book_obj.publish得到書對應的出版社對象,再.name得到出版社的名字 上海出版社
(2)查詢天津出版社出版過的書籍名稱(反向查詢,按表名小寫_set)
publish_obj = Publish.objects.filter(name="天津出版社").first() #得到name="天津出版社"的出版社對象 print(publish_obj.book_set.all()) # 得到出版社出版的書籍的對象集合:<QuerySet [<Book: go>, <Book: 操作系統原理>]> for book in publish_obj.book_set.all(): print(book.title) #遍歷得到結果:go和操作系統原理
3、多對多關系
(1)查詢(1)查詢書名為go的所有作者的名字(正向查詢,按字段)
obj = Book.objects.filter(title="go").first() #得到書名為go的對象 for i in obj.author.all(): # obj.author.all()得到對應作者的集合 print(i.name) # 遍歷得到結果:wang和zhang
(2)查詢zhang出版過的所有書籍名稱(反向查詢,按表名小寫_set)
obj = Author.objects.filter(name="zhang").first() #得到名字為"zhang"的作者的對象 for i in obj.book_set.all(): # obj.book_set.all()得到對應書籍的集合 print(i.title) # 遍歷得到結果:go,操作系統原理,Linux,python print(obj.book_set.all().values("title")) # 結果:<QuerySet [{'title': 'go'}, {'title': '操作系統原理'}, {'title': 'Linux'}, {'title': 'python'}]>
三、基於queryset查詢
1、一對一關系
(1)查詢wang的手機號(反向查詢,按表名小寫)
ret = Author.objects.filter(name="wang").values("authordetail__tel") print(ret) # 結果:<QuerySet [{'authordetail__tel': '18971232312'}]>
(2)查詢手機號為13451222125的作者的名字 (正向查詢,按字段)
ret = AuthorDetail.objects.filter(tel="13451222125").values("author__name") print(ret) # 結果:<QuerySet [{'author__name': 'li'}]>
2、一對多關系
(1)查詢id=15的書籍的出版社的名稱(正向查詢,按字段)
ret = Book.objects.filter(id=15).values("publish__name") print(ret) # 結果:<QuerySet [{'publish__name': '上海出版社'}]>
(2)查詢天津出版社出版過的書籍名稱(反向查詢,按表名小寫)
ret = Publish.objects.filter(name="天津出版社").values("book__title") print(ret) # 結果:<QuerySet [{'book__title': 'go'}, {'book__title': '操作系統原理'}]>
3、多對多關系
(1)查詢(1)查詢書名為go的所有作者的名字(正向查詢,按字段)
ret = Book.objects.filter(title="go").values("author__name") print(ret) # 結果:<QuerySet [{'author__name': 'wang'}, {'author__name': 'zhang'}]>
(2)查詢zhang出版過的所有書籍名稱(反向查詢,按表名小寫)
ret = Author.objects.filter(name="zhang").values("book__title") print(ret) # 結果:<QuerySet [{'book__title': 'go'}, {'book__title': 'python'}, {'book__title': '操作系統原理'}, {'book__title': 'Linux'}]>
# 查詢手機號以1開頭的作者出版過的所有書籍名稱以及出版社名稱
ret=AuthorDetail.objects.filter(tel__startswith="189").values("author__book__title","author__book__publish__name") print(ret) #結果是:<QuerySet [{'author__book__title': 'go', 'author__book__publish__name': '天津出版社'}, {'author__book__title': 'css', 'author__book__publish__name': '上海出版社'}, {'author__book__title': '操作系統原理', 'author__book__publish__name': '天津出版社'}, {'author__book__title': 'Linux', 'author__book__publish__name': '河北出版社'}]>
四、聚合和分組
from django.db.models import Avg, Count, Max, Min
1、統計所有書籍的平均價格
ret = Book.objects.all().aggregate(c=Avg("price")) print(ret) # 結果是:{'c': 249.5}
2、查詢每一個出版社出版的書籍個數
ret = Publish.objects.all().annotate(c=Count("book")).values("name", "c") print(ret) # 結果是:<QuerySet [{'name': '北京出版社', 'c': 0}, {'name': '上海出版社', 'c': 2}, {'name': '天津出版社', 'c': 2}, {'name': '河北出版社', 'c': 1}, {'name': '唐山出版社', 'c': 1}]>
3、查詢每一個作者出版的書籍的平均價格
ret = Author.objects.all().annotate(price_avg=Avg("book__price")).values("name", "price_avg") print(ret) # 結果是:<QuerySet [{'name': 'song', 'price_avg': 252.25}, {'name': 'wang', 'price_avg': 230.0}, {'name': 'li', 'price_avg': 280.0}, {'name': 'zhang', 'price_avg': 280.0}, {'name': 'zhao', 'price_avg': None}, {'name': 'zhou', 'price_avg': None}]>
4、查詢每一本書籍名稱以及作者的個數
ret = Book.objects.all().annotate(author_num=Count("author")).values("title", "author_num") print(ret) # 結果是:<QuerySet [{'title': 'linux', 'author_num': 2}, {'title': 'css', 'author_num': 2}, {'title': 'go', 'author_num': 2}, {'title': '操作系統原理', 'author_num': 3}, {'title': 'Linux', 'author_num': 4}, {'title': 'python', 'author_num': 3}]>
5、查詢價格大於200的每一本書籍名稱以及作者的個數
ret = Book.objects.filter(price__gt=200).annotate(author_num=Count("author")).values("title", "author_num") print(ret) # 結果是:<QuerySet [{'title': 'linux', 'author_num': 2}, {'title': 'go', 'author_num': 2}, {'title': 'python', 'author_num': 3}, {'title': '操作系統原理', 'author_num': 3}, {'title': 'Linux', 'author_num': 4}]>
五、F查詢和Q查詢
from django.db.models import F,Q
1、F查詢
(1)查找comment_num數量大於poll_num的書
ret = Book.objects.filter(comment_num__gt=F("poll_num")) print(ret)
(2)查找comment_num數量大於10倍的poll_num的書
ret = Book.objects.filter(comment_num__gt=F("read_num") * 10) print(ret)
(3)把所有書的價格都加100
Book.objects.all().update(price=F("price") + 100)
2、Q查詢
(1)查找以Java開頭並且價格大於200的書
ret = Book.objects.filter(title__startswith="java", price__gt=200) print(ret)
(2)查找以Java開頭或者價格小於200的書
ret = Book.objects.filter(Q(title__startswith="java") | Q(price__lt=200)) print(ret)
(3)查找2017年出版的Java開頭的書或者2017年的價格小於200的書
ret = Book.objects.filter(Q(title__startswith="java") | Q(price__lt=200), create_time__year=2017, ) print(ret)
Django之ORM跨表操作