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 查询的主要内容,如果未能解决你的问题,请参考以下文章

Django - 原始 SQL 查询或 Django QuerySet ORM

django的 ORM 操作 增加和查询

django模型层 ORM查询

Django聚合查询 orm字段及属性

django-模型层(ORM语法)

django-模型层(ORM语法)