• 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)))
    
                
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
                
    代码






  • 相关阅读:
    CCPlatformConfig(设置执行平台 iOS android win32等。。。)
    LeetCode Add Binary |My Solution
    actor中!(tell)与forward的差别
    二叉查找树(二叉排序树)创建,插入,删除操作。
    程序猿技术练级攻略
    poj 2236 Wireless Network 【并查集】
    leetcode 题解 || Letter Combinations of a Phone Number 问题
    创业之前 ——Paul Graham 最新博文
    linux-文件系统基本概念
    上拉电阻和下拉电阻的用处和区别
  • 原文地址:https://www.cnblogs.com/knighterrant/p/10386189.html
Copyright © 2020-2023  润新知