zoukankan      html  css  js  c++  java
  • 057.Python前端Django模型ORM多表查询


    一 基于对象的查询

    1.1 一对多查询

    设计路由

    复制代码
    from django.contrib import admin
    from django.urls import path
    from app01 import views
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('add_book/',views.add_book),
        path('query_book/',views.query_book),
    ]
    复制代码

    视图函数

    查询主键为1的书籍出版社所在的城市

    mysql> select * from app01_book;

    复制代码
    +----+--------------+--------+------------+------------+
    | id | title        | price  | pub_date   | publish_id |
    +----+--------------+--------+------------+------------+
    |  1 | 独孤九剑     | 130.00 | 2007-10-03 |       NULL |
    |  2 | 吸星大法     | 110.00 | 2017-10-03 |          1 |
    +----+--------------+--------+------------+------------+
    复制代码

    重新把null改为1

    mysql> update app01_book set publish_id=1 where id=1;

    mysql> select * from app01_book;

    复制代码
    +----+--------------+--------+------------+------------+
    | id | title        | price  | pub_date   | publish_id |
    +----+--------------+--------+------------+------------+
    |  1 | 独孤九剑     | 130.00 | 2007-10-03 |          1 |
    |  2 | 吸星大法     | 110.00 | 2017-10-03 |          1 |
    +----+--------------+--------+------------+------------+
    复制代码

    正向查询

    book--------------------------------------------->publish:按字段

    root@darren-virtual-machine:~/PycharmProjects/orm_demo# vim app01/views.py

    def query_book(request):
        book_obj = models.Book.objects.filter(pk=1).first()     #拿到pk=1的书的对象
        print(book_obj.publish.city)                            #正向获取,publish表的数据
        return HttpResponse("查询成功")

    访问http://127.0.0.1:8000/query_book/

     

     查看输出结果

    反向获取

    按小写表名加下划线set

    复制代码
    def query_book(request):
        #book_obj = models.Book.objects.filter(pk=1).first()
        #print(book_obj.publish.city)
        #查询华山出版社所有的书籍名
        pub_obj = models.Publish.objects.filter(name="华山出版社").first()
        for book in pub_obj.book_set.all():
            print(book.title)
    
        return HttpResponse("查询成功")
    复制代码

    查看输出结果

    1.2 一对一查询

    正向查询

    def query_book(request):
        #查询令狐冲电话
        author_obj = models.Author.objects.filter(name="令狐冲").first()
        print(author_obj.au_detail.tel)
        return HttpResponse("查询成功")

    访问http://127.0.0.1:8000/query_book/

    结果

    [06/Apr/2020 13:48:28] "GET /query_book/ HTTP/1.1" 200 12
    13432335433

    反向查询

    在这里不用适应_set,是因为前面是一对多,这里是一对一,就不需要使用

    复制代码
    def query_book(request):
        #book_obj = models.Book.objects.filter(pk=1).first()
        #print(book_obj.publish.city)
        #查询华山出版社所有的书籍名
        #pub_obj = models.Publish.objects.filter(name="华山出版社").first()
        #for book in pub_obj.book_set.all():
        #   print(book.title)
        #查询令狐冲电话
        #author_obj = models.Author.objects.filter(name="令狐冲").first()
        #print(author_obj.au_detail.tel)
        #查询所有住在黑木崖的作者姓名
        au_detail_list = models.AuthorDetail.objects.filter(addr="黑木崖")
        for au in au_detail_list:
            print(au)
            print(au.author.name)
        return HttpResponse("查询成功")
    复制代码

    访问http://127.0.0.1:8000/query_book/

    结果

    AuthorDetail object (2)
    任我行
    AuthorDetail object (3)
    任盈盈
    [06/Apr/2020 13:55:46] "GET /query_book/ HTTP/1.1" 200 12

    1.3 多对多关系查询

    mysql> select * from  app01_book_authors;

    复制代码
    +----+---------+-----------+
    | id | book_id | author_id |
    +----+---------+-----------+
    |  1 |       1 |         9 |
    |  5 |       2 |         8 |
    +----+---------+-----------+
    复制代码

    mysql> select * from app01_author;

    复制代码
    +----+-----------+-----+--------------+
    | id | name      | age | au_detail_id |
    +----+-----------+-----+--------------+
    |  7 | 令狐冲    |  25 |            1 |
    |  8 | 任我行    |  58 |            2 |
    |  9 | 任盈盈    |  23 |            3 |
    +----+-----------+-----+--------------+
    复制代码

    mysql> insert into app01_book_authors (book_id,author_id) values (1,7);

    mysql> select * from app01_book_authors;

    复制代码
    +----+---------+-----------+
    | id | book_id | author_id |
    +----+---------+-----------+
    |  7 |       1 |         7 |
    |  1 |       1 |         9 |
    |  5 |       2 |         8 |
    +----+---------+-----------+
    复制代码

    views文件

    复制代码
    def query_book(request):
        #book_obj = models.Book.objects.filter(pk=1).first()
        #print(book_obj.publish.city)
        #查询华山出版社所有的书籍名
        #pub_obj = models.Publish.objects.filter(name="华山出版社").first()
        #for book in pub_obj.book_set.all():
        #   print(book.title)
        #查询令狐冲电话
        #author_obj = models.Author.objects.filter(name="令狐冲").first()
        #print(author_obj.au_detail.tel)
        #查询所有住在黑木崖的作者姓名
        # au_detail_list = models.AuthorDetail.objects.filter(addr="黑木崖")
        #for au in au_detail_list:
        #    print(au)
        #    print(au.author.name)
        #查出独孤九剑的所有作者和电话
        book_obj = models.Book.objects.filter(title="独孤九剑").first()
        for au in book_obj.authors.all():
            print(au.name,au.au_detail.tel)
        return HttpResponse("查询成功")
    复制代码

    访问http://127.0.0.1:8000/query_book/

    结果

    令狐冲 13432335433
    任盈盈 13878934322
    [06/Apr/2020 14:21:34] "GET /query_book/ HTTP/1.1" 200 12

    方法二

    复制代码
    def query_book(request):
        #book_obj = models.Book.objects.filter(pk=1).first()
        #print(book_obj.publish.city)
        #查询华山出版社所有的书籍名
        #pub_obj = models.Publish.objects.filter(name="华山出版社").first()
        #for book in pub_obj.book_set.all():
        #   print(book.title)
        #查询令狐冲电话
        #author_obj = models.Author.objects.filter(name="令狐冲").first()
        #print(author_obj.au_detail.tel)
        #查询所有住在黑木崖的作者姓名
        # au_detail_list = models.AuthorDetail.objects.filter(addr="黑木崖")
        #for au in au_detail_list:
        #    print(au)
        #    print(au.author.name)
        #查出独孤九剑的所有作者和电话
        #book_obj = models.Book.objects.filter(title="独孤九剑").first()
        #for au in book_obj.authors.all():
        #   print(au.name,au.au_detail.tel)
        #查询令狐冲所有的书籍名称
        au_obj = models.Author.objects.filter(name="令狐冲").first()
        for book in au_obj.book_set.all():
            print(book.title)
    
        return HttpResponse("查询成功")
    复制代码

    反向查询

    访问http://127.0.0.1:8000/query_book/

    结果

    独孤九剑
    [06/Apr/2020 14:26:24] "GET /query_book/ HTTP/1.1" 200 12

    二 基于双下划线的跨表查询

    Django 还提供了一种直观而高效的方式在查询(lookups)中表示关联关系,它能自动确认 SQL JOIN 联系。要做跨关系查询,就使用两个下划线来链接模型(model)间关联字段的名称,直到最终链接到你想要的model 为止。

    2.1 一对多

    正向查询按字段,反向查询按表名小写用来告诉ORM引擎join哪张表

    views视图文件

    复制代码
    def query_book(request):
        #book_obj = models.Book.objects.filter(pk=1).first()
        #print(book_obj.publish.city)
        #查询华山出版社所有的书籍名
        #pub_obj = models.Publish.objects.filter(name="华山出版社").first()
        #for book in pub_obj.book_set.all():
        #   print(book.title)
        #查询令狐冲电话
        #author_obj = models.Author.objects.filter(name="令狐冲").first()
        #print(author_obj.au_detail.tel)
        #查询所有住在黑木崖的作者姓名
        # au_detail_list = models.AuthorDetail.objects.filter(addr="黑木崖")
        #for au in au_detail_list:
        #    print(au)
        #    print(au.author.name)
        #查出独孤九剑的所有作者和电话
        #book_obj = models.Book.objects.filter(title="独孤九剑").first()
        #for au in book_obj.authors.all():
        #   print(au.name,au.au_detail.tel)
        #查询令狐冲所有的书籍名称
        #au_obj = models.Author.objects.filter(name="令狐冲").first()
        #for book in au_obj.book_set.all():
        #    print(book.title)
        #基于双下划线查询
        #一对多,查询华山出版社出版过的所有书籍和价格
        books = models.Publish.objects.filter(name="华山出版社").values("book__title","book__price")
        print(books)
        #反向
        books = models.Book.objects.filter(publish__name="华山出版社").values("title","price")
        print(books)
        return HttpResponse("查询成功")
    复制代码

    访问http://127.0.0.1:8000/query_book/

    结果

    <QuerySet [{'book__title': '独孤九剑', 'book__price': Decimal('130.00')}, {'book__title': '吸星大法', 'book__price': Decimal('110.00')}]>
    <QuerySet [{'title': '独孤九剑', 'price': Decimal('130.00')}, {'title': '吸星大法', 'price': Decimal('110.00')}]>
    [07/Apr/2020 06:39:31] "GET /query_book/ HTTP/1.1" 200 12

    2.2 多对多查询

    views视图文件

    复制代码
    def query_book(request):
        #book_obj = models.Book.objects.filter(pk=1).first()
        #print(book_obj.publish.city)
        #查询华山出版社所有的书籍名
        #pub_obj = models.Publish.objects.filter(name="华山出版社").first()
        #for book in pub_obj.book_set.all():
        #   print(book.title)
        #查询令狐冲电话
        #author_obj = models.Author.objects.filter(name="令狐冲").first()
        #print(author_obj.au_detail.tel)
        #查询所有住在黑木崖的作者姓名
        # au_detail_list = models.AuthorDetail.objects.filter(addr="黑木崖")
        #for au in au_detail_list:
        #    print(au)
        #    print(au.author.name)
        #查出独孤九剑的所有作者和电话
        #book_obj = models.Book.objects.filter(title="独孤九剑").first()
        #for au in book_obj.authors.all():
        #   print(au.name,au.au_detail.tel)
        #查询令狐冲所有的书籍名称
        #au_obj = models.Author.objects.filter(name="令狐冲").first()
        #for book in au_obj.book_set.all():
        #    print(book.title)
        #基于双下划线查询
        #一对多,查询华山出版社出版过的所有书籍和价格
        #books = models.Publish.objects.filter(name="华山出版社").values("book__title","book__price")
        #print(books)
        #反向
        #books = models.Book.objects.filter(publish__name="华山出版社").values("title","price")
        #print(books)
        #多对多,查出令狐冲出国所有的书籍的名字
        books = models.Book.objects.filter(authors__name="令狐冲").values("title")
        print(books)
        books = models.Author.objects.filter(name="令狐冲").values("book__title")
        print(books)
        return HttpResponse("查询成功")
    复制代码

    访问http://127.0.0.1:8000/query_book/

    结果

    <QuerySet [{'title': '独孤九剑'}]>
    <QuerySet [{'book__title': '独孤九剑'}]>

    三 聚合查询和分组查询

    3.1 聚合查询aggregate

    aggregate()是QuerySet 的一个终止子句,意思是说,它返回一个包含一些键值对的字典。键的名称是聚合值的标识符,值是计算出来的聚合值。键的名称是按照字段和聚合函数的名称自动生成出来的。如果你想要为聚合值指定一个名称,可以向聚合子句指定它

    views视图文件

    def query_book(request):
        #聚合查询
        from django.db.models  import Avg,Max,Min,Count,Sum
        books = models.Book.objects.aggregate(Avg("price"))
        print(books)

    访问http://127.0.0.1:8000/query_book/

    结果

    {'price__avg': Decimal('120.000000')}
    [07/Apr/2020 09:25:27] "GET /query_book/ HTTP/1.1" 200 12

    如果你希望生成不止一个聚合,你可以向aggregate() 子句中添加另一个参数。所以,如果你也想知道所有图书价格的最大值和最小值,可以这样查询:

    views视图文件

    def query_book(request):
        #聚合查询
        from django.db.models  import Avg,Max,Min,Count,Sum
        books = models.Book.objects.aggregate(Avg("price"),Max("price"),Min("price"))
        print(books)

    访问http://127.0.0.1:8000/query_book/

    结果

    [07/Apr/2020 09:58:04] "GET /query_book/ HTTP/1.1" 200 12
    {'price__avg': Decimal('120.000000'), 'price__max': Decimal('130.00'), 'price__min': Decimal('110.00')}

    3.2 分组查询-单表操作

    首先建一个表的模型

    复制代码
    from django.db import models
    
    # Create your models here.
    class Book(models.Model):
        title = models.CharField(max_length=32)
        price = models.DecimalField(max_digits=5, decimal_places=2)
        pub_date = models.DateField()
        publish = models.ForeignKey("Publish", on_delete=models.CASCADE,null=True)
        authors = models.ManyToManyField("Author")
    
    
    class Publish(models.Model):
        name = models.CharField(max_length=32)
        city = models.CharField(max_length=64)
        email = models.EmailField()
    
    
    class Author(models.Model):
        name = models.CharField(max_length=32)
        age = models.SmallIntegerField()
        au_detail = models.OneToOneField("AuthorDetail", on_delete=models.CASCADE)
    
    
    class AuthorDetail(models.Model):
        gender_choices = (
            (0, "女"),
            (1, "男"),
            (2, "保密"),
        )
        gender = models.SmallIntegerField(choices=gender_choices)
        tel = models.CharField(max_length=32)
        addr = models.CharField(max_length=64)
        birthday = models.DateField()
    #新加部分
    class Emp(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        salary = models.DecimalField(max_digits=8, decimal_places=2)
        dep = models.CharField(max_length=32)
        province = models.CharField(max_length=32)
    复制代码

    执行迁移操作

    复制代码
    root@darren-virtual-machine:~/PycharmProjects/orm_demo# python3 manage.py makemigrations
    Migrations for 'app01':
      app01/migrations/0003_emp.py
        - Create model Emp
    root@darren-virtual-machine:~/PycharmProjects/orm_demo# python3 manage.py migrate
    Operations to perform:
      Apply all migrations: admin, app01, auth, contenttypes, sessions
    Running migrations:
      Applying app01.0003_emp... OK
    复制代码

    向Emp表中插入数据

    复制代码
    mysql> select * from app01_emp;
    mysql> INSERT INTO `app01_emp` (`id`, `name`, `age`, `salary`, `dep`, `province`) VALUES ('1', '令狐冲', '24', '6000.00', '销售部', '河南');
    Query OK, 1 row affected (0.00 sec)
    mysql> INSERT INTO `app01_emp` (`id`, `name`, `age`, `salary`, `dep`, `province`) VALUES ('2', '任盈盈', '18', '8000.00', '公关部', '广东');
    Query OK, 1 row affected (0.00 sec)
    mysql> INSERT INTO  `app01_emp` (`id`, `name`, `age`, `salary`, `dep`, `province`) VALUES ('3', '任我行', '56', '10000.00', '销售部', '广东');
    Query OK, 1 row affected (0.00 sec)
    mysql> INSERT INTO `app01_emp` (`id`, `name`, `age`, `salary`, `dep`, `province`) VALUES ('4', '岳灵珊', '19', '6000.00', '公关部', '河南');
    Query OK, 1 row affected (0.00 sec)
    mysql> INSERT INTO  `app01_emp` (`id`, `name`, `age`, `salary`, `dep`, `province`) VALUES ('5', '小龙女', '20', '8000.00', '公关部', '河北');
    Query OK, 1 row affected (0.00 sec)
    复制代码

    查看数据

    查询操作:

    mysql> select dep, count(1) from app01_emp group by dep;

    mysql> select dep, avg(salary) from app01_emp GROUP BY dep;

    使用orm

    views视图文件

    复制代码
    def query_book(request):
        from django.db.models  import Avg,Max,Min,Count,Sum
        #单表分组查询
        dep = models.Emp.objects.values('dep').annotate(c=Count('id'))
        print(dep)
        sa = models.Emp.objects.values('dep').annotate(a=Avg('salary'))
        print(sa)
        return HttpResponse("查询成功")
    复制代码

    访问http://127.0.0.1:8000/query_book/

    结果

    <QuerySet [{'dep': '销售部', 'c': 2}, {'dep': '公关部', 'c': 3}]>
    <QuerySet [{'dep': '销售部', 'a': Decimal('8000.000000')}, {'dep': '公关部', 'a': Decimal('7333.333333')}]>
    [07/Apr/2020 10:53:14] "GET /query_book/ HTTP/1.1" 200 12

    3.3 分组操作-多表查询

    表结构

    复制代码
    class Emps(models.Model):
        name = models.CharField(max_length=32)
        age = models.IntegerField()
        salary = models.DecimalField(max_digits=8, decimal_places=2)
        dep = models.ForeignKey("Dep", on_delete=models.CASCADE)
        province = models.CharField(max_length=32)
    
    
    class Dep(models.Model):
        title = models.CharField(max_length=32)
    复制代码

    执行数据库迁移操作

    复制代码
    root@darren-virtual-machine:~/PycharmProjects/orm_demo# python3 manage.py makemigrations
    Migrations for 'app01':
      app01/migrations/0004_dep_emps.py
        - Create model Dep
        - Create model Emps
    root@darren-virtual-machine:~/PycharmProjects/orm_demo# python3 manage.py migrate
    Operations to perform:
      Apply all migrations: admin, app01, auth, contenttypes, sessions
    Running migrations:
      Applying app01.0004_dep_emps... OK
    复制代码

    插入dep表数据

    mysql> INSERT INTO `app01_dep` (`id`, `title`) VALUES ('1', '销售部');
    mysql> INSERT INTO `app01_dep` (`id`, `title`) VALUES ('2', '公关部');

    插入emps表数据

    复制代码
    mysql> INSERT INTO `app01_emps` (`id`, `name`, `age`, `salary`, `province`, `dep_id`) VALUES ('2', '令狐冲', '24', '8000.00', '河南', '1');
    mysql> INSERT INTO `app01_emps` (`id`, `name`, `age`, `salary`, `province`, `dep_id`) VALUES ('3', '任盈盈', '18', '9000.00', '广东', '2');
    mysql> INSERT INTO `app01_emps` (`id`, `name`, `age`, `salary`, `province`, `dep_id`) VALUES ('4', '任我行', '57', '10000.00', '广东', '1');
    mysql> INSERT INTO `app01_emps` (`id`, `name`, `age`, `salary`, `province`, `dep_id`) VALUES ('5', '岳灵珊', '19', '6000.00', '河南', '2');
    mysql> INSERT INTO `app01_emps` (`id`, `name`, `age`, `salary`, `province`, `dep_id`) VALUES ('6', '小龙女', '20', '8000.00', '河北', '2');
    复制代码

    查看数据

    多表分组查询

    sq语句查询

    复制代码
    查询每一个部门名称以及对应的员工数
    mysql> select app01_dep.title,count(app01_emps.id) from app01_emps LEFT JOIN app01_dep ON  app01_emps.dep_id = app01_dep.id GROUP BY app01_emps.dep_id;
    +-----------+----------------------+
    | title     | count(app01_emps.id) |
    +-----------+----------------------+
    | 销售部    |                    2 |
    | 公关部    |                    3 |
    +-----------+----------------------+
    查询每一个部门名称以及对应的员工的平均工资
    mysql> select app01_dep.title,avg(app01_emps.salary) FROM app01_emps LEFT JOIN app01_dep ON app01_emps.dep_id = app01_dep.id GROUP BY app01_emps.dep_id;
    +-----------+------------------------+
    | title     | avg(app01_emps.salary) |
    +-----------+------------------------+
    | 销售部    |            9000.000000 |
    | 公关部    |            7666.666667 |
    +-----------+------------------------+
    复制代码

    使用orm

    views视图文件

    复制代码
    def query_book(request):      
        from django.db.models  import Avg,Max,Min,Count,Sum
        #查询每一个部门名称以及对应的员工数
        dep_count = models.Emps.objects.values("dep__title").annotate(c=Count("id"))
        print(dep_count)
        #查询每一个部门名称以及对应的员工的平均工资
        sa = models.Emps.objects.values("dep__title").annotate(a=Avg("salary"))
        print(sa)
        return HttpResponse("查询成功")
    复制代码

    结果

    <QuerySet [{'dep__title': '销售部', 'c': 2}, {'dep__title': '公关部', 'c': 3}]>
    <QuerySet [{'dep__title': '销售部', 'a': Decimal('9000.000000')}, {'dep__title': '公关部', 'a': Decimal('7666.666667')}]>
    [07/Apr/2020 11:43:21] "GET /query_book/ HTTP/1.1" 200 12

    统计每一个出版社价格最便宜的书

    sql语句

    mysql> select name,min(app01_book.price) from app01_publish LEFT JOIN app01_book on app01_book.publish_id = app01_publish.id GROUP BY app01_publish.name;

    统计每一本书的作者个数

    mysql> select title,count(NAME) from app01_book LEFT JOIN app01_book_authors ON app01_book.id = app01_book_authors.book_id LEFT JOIN app01_author ON app01_book_authors.author_id = app01_author.id GROUP BY app01_book.id;

     

    统计每一本以“吸”开头的书籍的作者个数

    mysql> select title,count(NAME) FROM app01_book LEFT JOIN app01_book_authors ON app01_book.id = app01_book_authors.book_id LEFT JOIN app01_author ON app01_book

     

    统计不止一个作者的图书名称

    复制代码
    SELECT
        title,
        count(NAME) AS num
    FROM
        app01_book
    LEFT JOIN app01_book_authors ON app01_book.id = app01_book_authors.book_id
    LEFT JOIN app01_author ON app01_author.id = app01_book_authors.author_id
    GROUP BY
        app01_book.id
    HAVING
        num > 1;
    复制代码

    根据一本图书作者数量的多少对查询集QuerySet进行排序

    复制代码
    mysql> SELECT
        ->     title,
        ->     count(author_id) AS num
        -> FROM
        ->     app01_book
        -> LEFT JOIN app01_book_authors ON app01_book.id = app01_book_authors.book_id
        -> LEFT JOIN app01_author ON app01_author.id = app01_book_authors.author_id
        -> GROUP BY
        ->     app01_book.id
        -> ORDER BY
        ->     num;
    复制代码

    查询各个作者出的书的总价格

    复制代码
    mysql> SELECT
        ->     NAME,
        ->     sum(price)
        -> FROM
        ->     app01_author
        -> LEFT JOIN app01_book_authors ON app01_author.id = app01_book_authors.author_id
        -> LEFT JOIN app01_book ON app01_book.id = app01_book_authors.book_id
        -> GROUP BY
        ->     app01_author.id;
    复制代码

    使用orm

    views视图文件

    复制代码
    rom django.shortcuts import render,HttpResponse
    from app01 import models
    # Create your views here.
    def add_book(request):
        if request.method == "GET":
            return render(request,"add_book.html")
        else:
            #获取数据
            title = request.POST.get("title")
            publish = request.POST.get("publish")
            price = request.POST.get("price")
            pub_date = request.POST.get("pub_date")
            #方式一,通过传对象的方式,首先获取对象
            #pub_obj = models.Publish.objects.filter(name=publish).first()
            #book_obj = models.Book.objects.create(title=title,price=price,pub_date=pub_date,publish=pub_obj)
            #books = models.Book.objects.create(title=title, price=price, pub_date=pub_date, publish_id=pub_obj.pk)
            #多对多,方式一
            #book = models.Book.objects.filter(title="独孤九剑").first()
            #ling = models.Author.objects.filter(name="令狐冲").first()
            #ying = models.Author.objects.filter(name="任盈盈").first()
            #book.authors.add(ling, ying)
            #方式二
            #book = models.Book.objects.filter(title="吸星大法").first()
            #ling = models.Author.objects.filter(name='令狐冲').first()
            #ying = models.Author.objects.filter(name='任我行').first()
            #book.authors.add(ling.pk, ying.pk)
            #author_obj = models.Author.objects.filter(au_detail_id=1).first()
            #print(author_obj)
            #author_obj.book_set.clear()
    
            pub_obj = models.Publish.objects.get(pk=1)
            book_obj = models.Book.objects.get(pk=1)
            pub_obj.book_set.remove(book_obj)
        return HttpResponse("新增成功")
    def query_book(request):
        #book_obj = models.Book.objects.filter(pk=1).first()
        #print(book_obj.publish.city)
        #查询华山出版社所有的书籍名
        #pub_obj = models.Publish.objects.filter(name="华山出版社").first()
        #for book in pub_obj.book_set.all():
        #   print(book.title)
        #查询令狐冲电话
        #author_obj = models.Author.objects.filter(name="令狐冲").first()
        #print(author_obj.au_detail.tel)
        #查询所有住在黑木崖的作者姓名
        # au_detail_list = models.AuthorDetail.objects.filter(addr="黑木崖")
        #for au in au_detail_list:
        #    print(au)
        #    print(au.author.name)
        #查出独孤九剑的所有作者和电话
        #book_obj = models.Book.objects.filter(title="独孤九剑").first()
        #for au in book_obj.authors.all():
        #   print(au.name,au.au_detail.tel)
        #查询令狐冲所有的书籍名称
        #au_obj = models.Author.objects.filter(name="令狐冲").first()
        #for book in au_obj.book_set.all():
        #    print(book.title)
        #基于双下划线查询
        #一对多,查询华山出版社出版过的所有书籍和价格
        #books = models.Publish.objects.filter(name="华山出版社").values("book__title","book__price")
        #print(books)
        #反向
        #books = models.Book.objects.filter(publish__name="华山出版社").values("title","price")
        #print(books)
        #多对多,查出令狐冲出国所有的书籍的名字
        #books = models.Book.objects.filter(authors__name="令狐冲").values("title")
        #print(books)
        #books = models.Author.objects.filter(name="令狐冲").values("book__title")
        #print(books)
        #聚合查询
        from django.db.models  import Avg,Max,Min,Count,Sum
        #books = models.Book.objects.aggregate(Avg("price"),Max("price"),Min("price"))
        #print(books)
        #单表分组查询
        #dep = models.Emp.objects.values('dep').annotate(c=Count('id'))
        #print(dep)
        #sa = models.Emp.objects.values('dep').annotate(a=Avg('salary'))
        #print(sa)
        #books = models.Publish.objects.values("name").annotate(min_price=Min("book__price"))
        #print(books)
        #查询每一个部门名称以及对应的员工数
        #dep_count = models.Emps.objects.values("dep__title").annotate(c=Count("id"))
        #print(dep_count)
        #查询每一个部门名称以及对应的员工的平均工资
        #sa = models.Emps.objects.values("dep__title").annotate(a=Avg("salary"))
        #print(sa)
        price = models.Publish.objects.values("name").annotate(min_price=Min("book__price"))
        print(price)
        count = models.Book.objects.annotate(num=Count('authors__name')).values("title", "num")
        print(count)
        author_count = models.Book.objects.filter(title__startswith="吸").annotate(num=Count('authors__name')).values("title", "num")
        print(author_count)
        books = models.Book.objects.annotate(num_author=Count("authors__name")).filter(num_author__gt=1).values("title")
        print(books)
        num = models.Book.objects.annotate(num_author=Count("authors__name")).order_by("num_author").values("title", "num_author")
        print(num)
        sum_price = models.Author.objects.annotate(total=Sum("book__price")).values('name', 'total')
        print(sum_price)
        return HttpResponse("查询成功")
    复制代码

    对应六个结果

    复制代码
    <QuerySet [{'name': '华山出版社', 'min_price': Decimal('110.00')}, {'name': '明教出版社', 'min_price': None}]>
    <QuerySet [{'title': '独孤九剑', 'num': 2}, {'title': '吸星大法', 'num': 1}]>
    <QuerySet [{'title': '吸星大法', 'num': 1}]>
    <QuerySet [{'title': '独孤九剑'}]>
    <QuerySet [{'title': '吸星大法', 'num_author': 1}, {'title': '独孤九剑', 'num_author': 2}]>
    <QuerySet [{'name': '令狐冲', 'total': Decimal('130.00')}, {'name': '任盈盈', 'total': Decimal('130.00')}, {'name': '任我行', 'total': Decimal('110.00')}]>
    [07/Apr/2020 12:09:26] "GET /query_book/ HTTP/1.1" 200 12
    复制代码

    和使用sql语句对比,结果一样

    四 F查询与Q查询

    4.1 F查询

    在上面所有的例子中,我们构造的过滤器都只是将字段值与某个常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

    Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

    查询工资大于年龄的人

    复制代码
    from django.db.models import F, Q
        #查询工资大于年龄的人
        person = models.Emp.objects.filter(salary__gt=F('age'))
        print(person)
        #查询工资小于两倍年龄值的人
        people = models.Emp.objects.filter(salary__lt=F("age") * 2)
        print(people)
        #修改操作也可以使用F函数,比如将每一本书的价格提高100元
        models.Book.objects.update(price=F('price') + 100)
    复制代码

    查看数据库结果

    4.2 Q查询

    filter() 等方法中的关键字参数查询都是一起进行“AND” 的。 如果你需要执行更复杂的查询(例如OR 语句),你可以使用Q 对象。

    复制代码
    from django.db.models import F,Q
        #查询工资大于年龄的人
        #person = models.Emp.objects.filter(salary__gt=F('age'))
        #print(person)
        #查询工资小于两倍年龄值的人
        #people = models.Emp.objects.filter(salary__lt=F("age") * 2)
        #print(people)
        #修改操作也可以使用F函数,比如将每一本书的价格提高100元
        #models.Book.objects.update(price=F('price') + 100)
        # 查询价格大于220或者名称以吸开头的书籍
        books = models.Book.objects.filter(Q(price__gt=220) | Q(title__startswith="吸"))
        print(books)
        # 查询价格大于220或者不是2007年10月份的书籍
        books = models.Book.objects.filter(Q(price__gt=220)|~Q(Q(pub_date__year=2007)&Q(pub_date__month=10)))
        print(books)
        return HttpResponse("查询成功")
    复制代码

    得到结果

    <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>
    <QuerySet [<Book: Book object (1)>, <Book: Book object (2)>]>
    [07/Apr/2020 12:37:58] "GET /query_book/ HTTP/1.1" 200 12

    对照数据库,看结果

    学习记录,小白一枚
  • 相关阅读:
    net.sf.jsqlparser.statement.select.PlainSelect.getGroupByColumnReferences()Ljava/util/List(版本问题)
    Netty ByteBuf
    Vertx session 使用须知
    用Vert.x shiro jdbcRealm对restful api鉴权
    Vert.x发送 HTTP/HTTPS请求及重定向
    解决“hao123”劫持浏览器主页
    cannot find module bcrypt_lib.node
    nodejs运行项目报错TypeError: db.collection is not a function
    [Java] Stream flatMap
    [Spring Security] Authotization
  • 原文地址:https://www.cnblogs.com/wangsirde0428/p/14322898.html
Copyright © 2011-2022 走看看