• Django学习7


    分组查询

    from django.db.models import Avg, Max, Min, Count, Sum
    # 1.统计每个出版社出版的书籍的平均价格  (select avg(price) from app01_book GROUP BY publishs_id;)
        models.Book.objects.values('publishs_id').annotate(a=Avg('price'))
        
        models.Publish.objects.values('id').annotate(a=Avg('book__price'))
    
        models.Publish.objects.values('name').annotate(a=Avg('book__price'))
    
        # 这种写法默认按照publish的主键(id)进行分组
        models.Publish.objects.annotate(a=Avg('book__price')).values('name','a')
    	
    # 2.找出出版社出版的书籍的平均价格大于2的数据(相当于having过滤)
        models.Publish.objects.annotate(a=Avg('book__price')).values('name','a').filter(a__gt=2)
    
    

    F查询

    from django.db.models import F
        # F查询  --- 针对单张表内的字段进行操作
       
        # 1.查找书籍表中点赞数大于评论数的
        models.Book.objects.filter(good__gt=F('comment'))
    	
        # 支持运算
        models.Book.objects.filter(good__gt=F('comment')+20)
        
        # 2.所有书籍的价格都增加20
        models.Book.objects.all().update(price=F('price')+20)
    
    

    Q查询 ( 或 | 与 & 非~ )

    from django.db.models import Q
    # 1.评论数和点赞数都大于80的书籍
        models.Book.objects.filter(good__gt=80,comment__gt=80)
    
    # 2.评论数或点赞数大于80的书籍
        models.Book.objects.filter(Q(good__gt=80)|Q(comment__gt=80))
    
    # 3.点赞数小于等于80或评论数大于80的书籍
        models.Book.objects.filter(~Q(good__gt=80)|Q(comment__gt=80))
    
    # 3.点赞数和评论数都小于等于80的书籍
        models.Book.objects.filter(~Q(good__gt=80)&~Q(comment__gt=80))
    
    # Q可以嵌套,提高优先级.
    
    

    ORM执行原生SQL语句

    # raw (了解)
    # 查询所有出版社信息
    ret = models.Publish.objects.raw('select * from app01_publish;')
    print(ret)  # <RawQuerySet: select * from app01_publish;>
    for i in ret:
        print(i.name)
    
    # 直接执行自定义sql
    from django.db import connection
    cur = connection.cursor()
    cur.execute("""select * from app01_publish""")
    ret = cur.fetchone()
    print(ret)
    
    

    打印原生sql的两种方法

    # 通过connection(写上才会打印,可以单独查看)
    from django.db import connection
    ...
    print(connection.queries)
    
    # settings.py中设置(每次orm执行的时候都会打印)
    LOGGING = {
        'version': 1,
        'disable_existing_loggers': False,
        'handlers': {
            'console':{
                'level':'DEBUG',
                'class':'logging.StreamHandler',
            },
        },
        'loggers': {
            'django.db.backends': {
                'handlers': ['console'],
                'propagate': True,
                'level':'DEBUG',
            },
        }
    }
    
    

    ORM的坑

    查询每个作者出版的所有书的最高价格以及最高价格的那本书的名称

    情况一 : 设置了 sql_mode = only_full_group_by

    # ORM:
    models.Author.objects.annotate(m=Max('book__price')).values('name','m','book__title')
    # 报错! 与sql_mode = only_full_group_by不兼容
    # 设置了sql_mode = only_full_group_by,select的字段只能是分组依据的字段或聚合整理的数据
    

    解决方案

    SELECT
    	t1.`NAME`,
    	app01_book.title,
    	t1.max_price
    FROM
    	(SELECT
    			app01_author.id,
    			app01_author. NAME,
    			MAX(app01_book.price) max_price
    		FROM
    			app01_author
    		INNER JOIN app01_book_authors ON app01_author.id = app01_book_authors.author_id
    		INNER JOIN app01_book ON app01_book.id = app01_book_authors.book_id
    		GROUP BY
    			app01_author.id,
    			app01_author.`name`) AS t1
    INNER JOIN app01_book_authors ON t1.id = app01_book_authors.author_id
    INNER JOIN app01_book ON app01_book_authors.book_id = app01_book.id
    WHERE
    	t1.max_price = app01_book.price;
    
    # 思路:
    1.先连作者表,书籍-作者表和书籍表,找到作者id,作者姓名和出版的书中最高的价格;
    2.再将其作为一张大表,去连书籍-作者表和书籍表,其中连书籍表的时候用上价格和最高价格相同这个条件,来找到价格最高的书
    

    情况二 : 没有设置 sql_mode = only_full_group_by

    # 没有设置sql_mode = only_full_group_by的时候,分组后select非分组依据字段显示的内容会直接选取分组后的第一条作为展示,所以不会报错,但实际查询的数据是不正确的!
    

    解决方案

    # 思路:利用这个特点,我们先对价格进行一个降序,这样分组后它展示的第一条便恰好是我们所要查找的
    SELECT
    	*
    FROM
    	(SELECT
    			app01_author.id,
    			app01_book.title,
    			app01_book.price
    		FROM
    			app01_author
    		INNER JOIN app01_book_authors ON app01_author.id = app01_book_authors.author_id
    		INNER JOIN app01_book ON app01_book.id = app01_book_authors.book_id
    		ORDER BY
    			app01_book.price DESC) AS t1
    GROUP BY
    	t1.id;
    

    小结

    ORM也有做不到的事, 当ORM实现不了的就要把方向转向原生SQL语句(ORM执行原生SQL语句的方法见上面)

  • 相关阅读:
    Flask-1-05-Cookie&Session
    Flask-1-05-Response
    Flask-1-04-Request
    Python3 装饰器无参有参 Egon老师视频
    python魔法方法、构造函数、序列与映射、迭代器、生成器---python基础教程
    Python3(廖雪峰教程) 链接
    Python面向对象之私有属性和方法(转载)
    python3 isinstance
    生成器 讲得不错的帖子
    Python3 pickle模块
  • 原文地址:https://www.cnblogs.com/straightup/p/13453168.html
Copyright © 2020-2023  润新知