Django 的 orm 查询
Posted knighterrant
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Django 的 orm 查询相关的知识,希望对你有一定的参考价值。
一.模型关系表
1. 一对一
Author-AuthorDetail
关联字段可以在任意表下,但必须唯一约束。(unique约束)
ad_id(unique约束)
ad = models.oneToOneField("AuthorDetail",null=True,on_delete=models.CASCADE)
相当于 authors = models.ForgeinKey(to="Author",on_delete=models.CASCADE,unique)
2. 一对多
publish-book
关联字段在“多”的表中
建立ForgeinKey 约束
3. 多对多
book-author
关系表
foreinkey book_id references Book(id)
foreinkey author_id references Author(id)
authors = models.ManyToManyField("Author")
二.多表查询
a.一定要知道mysql 语句
b.增删改查
=========================================================================================================================
1. 添加
create
添加记录的思路:考虑 三种关系表的特殊字段
Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish_id=1) #数据库级别
def add(request):
======================绑定一对多关系===========================================
#一对多:(publish-book)
方式一:
Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish_id=1)
方式二:
pub_obj = Publish.objects.filter(name= "苹果出版社").first()
Book.objects.create(title="python",price=123,pub_date = "2012-11-12",publish=pub_obj)
python = Book.objects.filter(title="python").first()
python.publish #得到的是python这本书对应的出版社对象
===================绑定多对多关系:无非是在第3张关系表中创建记录=====================
正向操作按字段,反向操作按表名小写
#多对多:(authors-book)
key:一定要找到多对多关联属性在哪张表下,如Book下的authors,先找到book对象,再用该书籍对象
点关联字段
1.给python这本书绑定两个作者:alex egon
python = Book.objects.filter(title="python").first()
alex = Author.objects.filter(name="alex").first()
egon = Author.objects.filter(name="egon").first()
python.authors.add(alex,egon)
python.authors.add(1,2) #1,2分别为alex,egon的主键
python.authors.add(*[1,2,3,4,5]) #打散传
python.authors.remove(alex,egon)
python.authors.clear() #解除所有绑定
python.authors.set([1,]) #先清空,在赋值操作
2. 给alex作者绑定两本书籍 python和linux
alex = Author.objects.filter(name="alex").first()
python= Book.objects.filter(title="python").first()
linux= Book.objects.filter(title="linux").first()
alex.book_set.add(alex,linux)
==========================================================================================================================
2.查询
def queryset(request):
===============================基于对象的跨表查询================================
基于对象的跨表查询:(sql语句 子查询:以上一次的查询结果作为下一次的查询条件)
1.一对多:
正向查询按字段publish linux.publish
Book----------------------------------------------Publish
反向查询按表名小写_set.all()
1.查询linux这本书籍出版社的邮箱
linux = Book.objects.filter(title="linux").first()
print(linux.publish.emial)
2.查询苹果出版社出版的所有书籍
p1 = Publish.objects.filter(name="苹果出版社").first()
queryset = p1.book_set.all()
2. 多对多:
正向查询按字段authors book_obj.authors.all()
Book---------------------------------------------------Author
反向查询按表名小写_set().all()
1.查询linux这本书所有作者
linux= Book.objects.filter(title="linux").first()
queryset = linux.authors.all()
2.查询作者alex出版过的所有书籍
alex = Author.objects.filter(name="alex").first()
queryset = alex.book_set.all()
3. 一对一:
正向查询按字段ad, author_obj.ad
Author--------------------------------------------AuthorDetail
反向查询按表名小写 Authordetail_obj.author
1.查询alex手机号
alex= Author.objects.filter(name="alex").first()
alex.ad.telphone
2.查询手机号为123的作者
ad_obj = AuthorDetail.objects.filter(telphone=123).first()
print(ad_obj.author.name)
=================================基于双下滑线的跨表查询(join查询)=======================================
把多张表合成一张表,按单表查。
key: 通知orm引擎,进行跨表,正向查询按表名,反向查询按表名小写
1.一对多
1.查询linux这本书籍出版社的邮箱
sql :
select email from book inner join publish on book.publish_id = publish.id where book.title=‘linux‘
orm :(values 显示查询字段)
#方式一
queryset = Book.objects.filter(title="linux").values("publish__email")
#方式二
queryset = Publish.objects.filter(book__title = "linux").value("email")
2.多对多
1.查询linux这本书的所有作者名字
sql:
select author.name from book left join book2authors on book.id = book2authors.book_id
left join author on author.id = book2authors.author_id
where book.title="linux"
orm:
方式一:
queryset = Book.objects.filter(title="linux").values("authors__name")
left join 显示左边表中所有的数据
inner join如果基表没有数据就不显示第二个表中的那部分数据
方式二:
queryset = Author.objects.filter(book__title="linux").values(‘name‘)
3. 一多一
1.查询alex手机号
方式一:
queryset = Author.objects.filter(name="alex").values("ad__telphone")
方式二:
queryset = AuthorDetail.objects.filter(author__name="alex").values("telphone")
4.连续跨表查询
1.查询人民出版社出版过的所有书籍名称以及作者名字
Publish.objects.filter(name="人民出版社").values("book__name","book__authors__name")
Book.objects.filter(publish__name="人民出版社").values("name","authors__name")
2.手机号以151开头的作者出版过的所有书籍名称以及所有出版社名称
Author.objects.filter(ad__telphone__startswith=151).values("book__name","book__publish__name")
================================聚合和分组查询============================================
1.聚合(aggregate 只对一组进行统计)
from django.db.models import Avg,Count,Max,Min
1.计算所有图书的平均价格
Book.objects.all().aggregate(avg_price=Avg("price"))
2. 计算所有图书的最高价和最低价
Book.objects.all().aggregate(min_price=Min("price"),max_price=Max(‘price‘))
2.分组查询 (annotate 对多组数据进行统计)
1.单表分组:
emp
id name salary dep province
1 alex 20000 销售部 山东
2 egon 30000 人事部 河北
3 wang 40000 人事部 山东
查询 : 每个部门的名称以及员工人数
sql:
select dep,Count(*) from emp group by dep;
select dep,Avg(salary) from emp group by dep;
orm:
按哪个字段group by 就 values 哪个字段,用annotate 统计
1.查询每个部门的名字
queryset = Emp.objects.values("dep").annotate(c=Count("*"))
2.查询每个省份的平均薪水
queryset= Emp.objects.values("province").annotate(avg_salary=Avg("salary"))
2.多表分组:(多张关联表)
key:多张表join起来,再按单表查
1.查询每个出版社的名称以及出版过书籍的平均价格
sql:
select publish.name,Avg(book.price) from publish left join book on publish.id = book.publish_id
group by publish.id,publish.name
orm:
方式一:
queryset = Publish.objects.values("name","id").annotate(avg_price =avg("book__price"))
方式二:
queryset = Publish.objects.all().annotate(avg_price =avg("book__price"))
2.查询每一个作者的名字以及出版书籍的个数
方式一:
queryset = Author.objects.values("name").annotate(book_num=Count("book"))
方式二:
queryset = Author.objects.annotate(book_num=Count("book")).values("book_num","name")
3.查询每本书籍名称以及作者个数
queryset = Book.objects.annotate(c=Count("authors")).values("title",c)
4.查询作者个数大于1的书籍名称和作者个数
sql:
select book.tilte,Count(author.id) as c from book left join book2authors on book.id = book2authors.book_id
left join Author on book2authors.author_id
group by book.id
having c>1
orm:
queryset = Book.objects.annotate(c=Count("authors")).filter(c__gt=1).values("title","c")
(相当于having)
5.查询书籍名称包含“h"的书籍名称和作者个数
Book.objects.filter(title__icontains=‘h‘).annonate(c=Count(‘authors‘)).values("title",c)
(相当于where)
====================================F查询和Q查询===================================================
from django.db.models import F,Q,Avg
1.F查询
1.查询评论数大于100的文章
Article.objects.filter(comment_num__gt=100)
2.查询评论数大于点赞数的文章
Article.objects.filter(comment_num__gt=F(poll_num))
3.查询评论数大于100的所有文章
queryset = Article.objects.filter(comment_num__gt=F("poll_num")*2)
4.将所有书籍的价格提高一百元
Book.objects.update(price=F("price")+100)
2.Q查询 (|或 &且 ~非)
1.查询价格大于200或名称以"p"开头的书籍
queryset = Book.objects.all().filter(Q(price__gt=200)|Q(title__startswith="p")
2.查询价格大于300或出版日期(不是)为2019年一月份的书籍
queryset= Book.objects.filter(Q(price__gt=300)|~Q(Q(pub_date_year=2019)&Q(pub_date_month=1)))
一.模型关系表 1. 一对一 Author-AuthorDetail 关联字段可以在任意表下,但必须唯一约束。(unique约束) ad_id(unique约束) ad = models.oneToOneField("AuthorDetail",null=True,on_delete=models.CASCADE) 相当于 authors = models.ForgeinKey(to="Author",on_delete=models.CASCADE,unique) 2. 一对多 publish-book 关联字段在“多”的表中 建立ForgeinKey 约束 3. 多对多 book-author 关系表 foreinkey book_id references Book(id) foreinkey author_id references Author(id) authors = models.ManyToManyField("Author") 二.多表查询 a.一定要知道mysql 语句 b.增删改查 ========================================================================================================================= 1. 添加 create 添加记录的思路:考虑 三种关系表的特殊字段 Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish_id=1) #数据库级别 def add(request): ======================绑定一对多关系=========================================== #一对多:(publish-book) 方式一: Book.objects.create(title="python",price=123,pub_date="2012-12-12",publish_id=1) 方式二: pub_obj = Publish.objects.filter(name= "苹果出版社").first() Book.objects.create(title="python",price=123,pub_date = "2012-11-12",publish=pub_obj) python = Book.objects.filter(title="python").first() python.publish #得到的是python这本书对应的出版社对象 ===================绑定多对多关系:无非是在第3张关系表中创建记录===================== 正向操作按字段,反向操作按表名小写 #多对多:(authors-book) key:一定要找到多对多关联属性在哪张表下,如Book下的authors,先找到book对象,再用该书籍对象 点关联字段 1.给python这本书绑定两个作者:alex egon python = Book.objects.filter(title="python").first() alex = Author.objects.filter(name="alex").first() egon = Author.objects.filter(name="egon").first() python.authors.add(alex,egon) python.authors.add(1,2) #1,2分别为alex,egon的主键 python.authors.add(*[1,2,3,4,5]) #打散传 python.authors.remove(alex,egon) python.authors.clear() #解除所有绑定 python.authors.set([1,]) #先清空,在赋值操作 2. 给alex作者绑定两本书籍 python和linux alex = Author.objects.filter(name="alex").first() python= Book.objects.filter(title="python").first() linux= Book.objects.filter(title="linux").first() alex.book_set.add(alex,linux) ========================================================================================================================== 2.查询 def queryset(request): ===============================基于对象的跨表查询================================ 基于对象的跨表查询:(sql语句 子查询:以上一次的查询结果作为下一次的查询条件) 1.一对多: 正向查询按字段publish linux.publish Book----------------------------------------------Publish 反向查询按表名小写_set.all() 1.查询linux这本书籍出版社的邮箱 linux = Book.objects.filter(title="linux").first() print(linux.publish.emial) 2.查询苹果出版社出版的所有书籍 p1 = Publish.objects.filter(name="苹果出版社").first() queryset = p1.book_set.all() 2. 多对多: 正向查询按字段authors book_obj.authors.all() Book---------------------------------------------------Author 反向查询按表名小写_set().all() 1.查询linux这本书所有作者 linux= Book.objects.filter(title="linux").first() queryset = linux.authors.all() 2.查询作者alex出版过的所有书籍 alex = Author.objects.filter(name="alex").first() queryset = alex.book_set.all() 3. 一对一: 正向查询按字段ad, author_obj.ad Author--------------------------------------------AuthorDetail 反向查询按表名小写 Authordetail_obj.author 1.查询alex手机号 alex= Author.objects.filter(name="alex").first() alex.ad.telphone 2.查询手机号为123的作者 ad_obj = AuthorDetail.objects.filter(telphone=123).first() print(ad_obj.author.name) =================================基于双下滑线的跨表查询(join查询)======================================= 把多张表合成一张表,按单表查。 key: 通知orm引擎,进行跨表,正向查询按表名,反向查询按表名小写 1.一对多 1.查询linux这本书籍出版社的邮箱 sql : select email from book inner join publish on book.publish_id = publish.id where book.title=‘linux‘ orm :(values 显示查询字段) #方式一 queryset = Book.objects.filter(title="linux").values("publish__email") #方式二 queryset = Publish.objects.filter(book__title = "linux").value("email") 2.多对多 1.查询linux这本书的所有作者名字 sql: select author.name from book left join book2authors on book.id = book2authors.book_id left join author on author.id = book2authors.author_id where book.title="linux" orm: 方式一: queryset = Book.objects.filter(title="linux").values("authors__name") left join 显示左边表中所有的数据 inner join如果基表没有数据就不显示第二个表中的那部分数据 方式二: queryset = Author.objects.filter(book__title="linux").values(‘name‘) 3. 一多一 1.查询alex手机号 方式一: queryset = Author.objects.filter(name="alex").values("ad__telphone") 方式二: queryset = AuthorDetail.objects.filter(author__name="alex").values("telphone") 4.连续跨表查询 1.查询人民出版社出版过的所有书籍名称以及作者名字 Publish.objects.filter(name="人民出版社").values("book__name","book__authors__name") Book.objects.filter(publish__name="人民出版社").values("name","authors__name") 2.手机号以151开头的作者出版过的所有书籍名称以及所有出版社名称 Author.objects.filter(ad__telphone__startswith=151).values("book__name","book__publish__name") ================================聚合和分组查询============================================ 1.聚合(aggregate 只对一组进行统计) from django.db.models import Avg,Count,Max,Min 1.计算所有图书的平均价格 Book.objects.all().aggregate(avg_price=Avg("price")) 2. 计算所有图书的最高价和最低价 Book.objects.all().aggregate(min_price=Min("price"),max_price=Max(‘price‘)) 2.分组查询 (annotate 对多组数据进行统计) 1.单表分组: emp id name salary dep province 1 alex 20000 销售部 山东 2 egon 30000 人事部 河北 3 wang 40000 人事部 山东 查询 : 每个部门的名称以及员工人数 sql: select dep,Count(*) from emp group by dep; select dep,Avg(salary) from emp group by dep; orm: 按哪个字段group by 就 values 哪个字段,用annotate 统计 1.查询每个部门的名字 queryset = Emp.objects.values("dep").annotate(c=Count("*")) 2.查询每个省份的平均薪水 queryset= Emp.objects.values("province").annotate(avg_salary=Avg("salary")) 2.多表分组:(多张关联表) key:多张表join起来,再按单表查 1.查询每个出版社的名称以及出版过书籍的平均价格 sql: select publish.name,Avg(book.price) from publish left join book on publish.id = book.publish_id group by publish.id,publish.name orm: 方式一: queryset = Publish.objects.values("name","id").annotate(avg_price =avg("book__price")) 方式二: queryset = Publish.objects.all().annotate(avg_price =avg("book__price")) 2.查询每一个作者的名字以及出版书籍的个数 方式一: queryset = Author.objects.values("name").annotate(book_num=Count("book")) 方式二: queryset = Author.objects.annotate(book_num=Count("book")).values("book_num","name") 3.查询每本书籍名称以及作者个数 queryset = Book.objects.annotate(c=Count("authors")).values("title",c) 4.查询作者个数大于1的书籍名称和作者个数 sql: select book.tilte,Count(author.id) as c from book left join book2authors on book.id = book2authors.book_id left join Author on book2authors.author_id group by book.id having c>1 orm: queryset = Book.objects.annotate(c=Count("authors")).filter(c__gt=1).values("title","c") (相当于having) 5.查询书籍名称包含“h"的书籍名称和作者个数 Book.objects.filter(title__icontains=‘h‘).annonate(c=Count(‘authors‘)).values("title",c) (相当于where) ====================================F查询和Q查询=================================================== from django.db.models import F,Q,Avg 1.F查询 1.查询评论数大于100的文章 Article.objects.filter(comment_num__gt=100) 2.查询评论数大于点赞数的文章 Article.objects.filter(comment_num__gt=F(poll_num)) 3.查询评论数大于100的所有文章 queryset = Article.objects.filter(comment_num__gt=F("poll_num")*2) 4.将所有书籍的价格提高一百元 Book.objects.update(price=F("price")+100) 2.Q查询 (|或 &且 ~非) 1.查询价格大于200或名称以"p"开头的书籍 queryset = Book.objects.all().filter(Q(price__gt=200)|Q(title__startswith="p") 2.查询价格大于300或出版日期(不是)为2019年一月份的书籍 queryset= Book.objects.filter(Q(price__gt=300)|~Q(Q(pub_date_year=2019)&Q(pub_date_month=1)))
以上是关于Django 的 orm 查询的主要内容,如果未能解决你的问题,请参考以下文章