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)))

代码



原文地址:https://www.cnblogs.com/knighterrant/p/10386189.html

时间: 2024-08-30 15:01:26

Django 的 orm 查询的相关文章

Django 之 ORM 查询使有

一.在Django项目上运行python文件查询数据库 import os if __name__ == '__main__': #加载Django项目的配置信息 os.environ.setdefault("DJANGO_SETTINGS_MODULE","testinclude.settings") #导入Django,并启动Django项目 import django django.setup() from ormtest import models #查询所

django优化--ORM查询

ORM提供了两个方法用来优化查询效率 1. select_related 有两张表:表结构如下: class Scheme(models.Model): """ 套餐类 """ name = models.CharField(max_length=200, verbose_name="套餐名") coordinate = models.CharField(max_length=50, verbose_name="坐标

django知识之ORM查询

1. ORM字段 1. AutoField(primary_key=True)      -------->自增且主键 2. CharField(max_length=16)         --------->varchar类型(char类型可以自定义 类改写db_type) 3. IntegerField(null=True) --> 最大10位    -------->int类型(最大10位所以手机号码一般用char或者varchar类型) 4. DateField(auto

django指定mysql数据库 ORM查询

django原生自带数据库,不过自带的数据库是sqlite 这次使用的orm框架操作数据库 这时候你就需要换上你想用的数据库比如大众化的mysql 但是你还是首先要先安装pymysql的驱动 pip install PyMySQL 在Django的工程同名子目录的__init__.py文件中添加如下语句 from pymysql import install_as_MySQLdb install_as_MySQLdb()django 在python2.7一直使用的是db操作数据库由于django

Django—— ORM查询(sql优化)优化了解,Django(元信息)元类建索引

Django(元信息)元类建索引 索引:索引的一个主要目的就是加快检索表中数据,索引是经过某种算法优化过的,因而查找次数要少的多.可见,索引是用来定位的. class Book(models.Model) name = models.CharField(max_length=64) class Meta: # 自定义表名 db_table = 'table_name' # 联合索引: 索引的一个主要目的就是加快检索表中数据 index_together = ('tag1', 'tag2') #

Python - Django - ORM 查询方法

models.py: from django.db import models class Human(models.Model): id = models.AutoField(primary_key=True) name = models.CharField(max_length=32) age = models.IntegerField() birthday = models.DateField(auto_now_add=True) 在数据库中添加几条数据 在 Python 脚本中调用 Dj

python 之 Django框架(orm单表查询、orm多表查询、聚合查询、分组查询、F查询、 Q查询、事务、Django ORM执行原生SQL)

12.329 orm单表查询 import os if __name__ == '__main__': # 指定当前py脚本需要加载的Django项目配置信息 os.environ.setdefault("DJANGO_SETTINGS_MODULE", "orm_demo.settings") import django django.setup() # 启动Django项目 from app01 import models #返回QuerySet对象的方法: r

django模型层 、 ORM查询

模型层 ORM查询 单表查询 前期准备工作需求: 如何只单独测试django中的某一个py文件 如何书写测试脚本 如何使用: 在任意一个py文件中书写以下代码 应用下的tests 或者自己新建一个 import os if __name__ == "__main__": os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day53.settings") import django django.se

Django的ORM表查询

目录 Django的ORM表查询 单表查询 多表查询 聚合查询 分组查询 F与Q查询 Django的ORM表查询 先创建一个数据库,做前期准备 为了方便测试,不再进行urls对应关系和views的书写,直接测试的单个文件 那么如何只单独测试Django中的某个py文件,有以下方法 在任意一个py文件中书写以下代码 可以在应用app的目录下的tests.py中书写 也可以自己建立一个py文件书写 import os if __name__ == "__main__": os.enviro