Django之ORM跨表操作
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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跨表操作的主要内容,如果未能解决你的问题,请参考以下文章
Django之ORM跨表操作(聚合查询,分组查询,F和Q查询等)
第六模块:WEB框架开发 第1章·Django框架开发50~100