ICode9

精准搜索请尝试: 精确搜索
首页 > 数据库> 文章详细

ORM之聚合查询,分组查询,F查询,Q查询,ORM查询优化,事务操作,常见字段及参数,多对多三种表的创建

2022-10-20 18:04:05  阅读:276  来源: 互联网

标签:公交查询 查询处理 查询器 查询语言 查询方法 查询 查询数据库


一:正反向进阶操作
1.查询主键为1的书籍对应的出版社名称和书名

models.Publish.objects.filter(book__pk=1).values(name,book__title)
models.Author.objects.filter(book__pk=3).values(name,book__title)
models.AuthorDetail.objects.filter(author__name=jason).values(phone, addr)
4.查询南方出版社出版的书籍的名称及价格

models.Book.objects.filter(publish__name=南方出版社).values(title, price)
5.查询jason写过的书名和日期

models.Book.objects.filter(authors__name=jason).values(title, publish_date)
models.Author.objects.filter(book__pk=1).values(author_detail__phone)
models.AuthorDetail.objects.filter(author__book__pk=1).values(phone)
二:聚合查询
1.首先第一步需要导入模块

from django.db.models import Max, Min, Sum, Avg, Count
2.没分组之前聚合查询需要使用关键字aggregate

models.Book.objects.aggregate(Max(price), Min(price),Count(pk))
三:分组查询
1.如何取消分组之后默认只能够获取分组字段的特性?
将sql_mode中的only_full_group_by配置移除即可
# 第一步:在终端进入mysql,输入以下指令
set global sql_mode = STRICT_TRANS_TABLES
# 第二步:退出mysql
# 第三步:重新进入mysql即可
2.分组查询练习
1.按照整条数据分组
models.Book.objects.annotate()
models.Book.objects.annotate(author_num=Count(authors__pk)).values(author_num)
2.按照表中某个字段分组
按照annotate前面values括号中的字段分组

models.Book.objects.values(title).annatate()
案例2:统计每一个出版社的数的数量

models.Book.objects.values(publish_id).annotate(book_num=Count(pk)).values(book_num)
案例3:统计出每个出版社卖的最便宜的书的价格

models.Publish.objects.annotate(min_price=Min(book__price)).values(name,min_price)
models.Book.objects.annotate(author_num=Count(authors__pk)).filter(author_num__gt=1).values(title, author_num)
models.Author.objects.annotate(sum_price=Sum(book__price)).values(name,sum_price)
四:F查询
1.F查询条件不是自定义的,而是来自于表中的字段

首先需要导入F模块

from django.db.models import F
案例1:查询库存数大于卖出数的书籍

models.Book.objects.filter(stock_num__gt=F(sale_num))
案例2:将所有的书籍价格上涨1000块

models.Book.objects.update(price=F(price)+1000)
案例3:将主键为1的书籍名称加上爆款后缀

from django.db.models.functions import Concat
from django.db.models import Value

models.Book.objects.filter(pk=1).update(title=Concat(F(title), Value(爆款)))
五:Q查询
1.默认是and关系

models.Book.objects.filter(pk=1, publish_id=3)
2.逗号分割还是and关系

models.Book.objects.filter(Q(pk=1), Q(piblish_id=3))
3…管道符是or的关系

models.Book.objects.filter(Q(pk=1) | Q(publish_id=3))
4.波浪号是not关系

models.Book.objects.filter(~Q(pk=1) | Q(publish_id=3))
5.Q查询可以可以将查询条件的字段改为字符串形式

q_obj = Q()
q_obj.connector = or  # q对象默认的多个条件是and关系
q_obj.children.append((pk,1))
q_obj.children.append((publish_id,3))
res = models.Book.objects.filter(q_obj)
print(res)
六:ORM查询优化
1.django中orm自带的两个优化机制
1.orm默认都是惰性查询:当后续需要的时候才会真正执行 2.orm自带limit分页:减轻数据库和服务器端的压力
2.only与defer
2.1.only
res = models.Book.objects.only(title, price)
for obj in res:
    print(obj.title)
    print(obj.price)
    print(obj.publish_time)
only会将括号内填写的字段封装成一个个的数据对象,对象在点击的时候不会再走数据库查询,但是对象点括号中没有的字段的时候,每次都会走数据库

总结:对象点only括号内有的字段不会走数据库,点括号中没有的字段会走数据库

2.2.defer
res = models.Book.objects.defer(title, price)
for obj in res:
    print(obj.title)
    print(obj.price)
    print(obj.publish_time)
总结:对象点defer括号内有的字段会走数据库,点括号中没有的字段不会走数据库

3.select_related与prefetch_related
3.1.select_related
res = models.Book.objects.select_related(authors)
for obj in res:
    print(obj.publish.name)
总结:

1.select_related括号内只能接收外键字段(一对一,一对多) 2.自动连表 3.得到数据对象直接点表中的字段得到相应的数据 4.不会再走数据库查询
3.2prefetch_related
res = models.Book.objects.prefetch_related(publish)
for obj in res:
    print(obj.publish.name)
总结:

1.底层其实就是子查询 2.将子查询之后的结果一次性封装到数据对象中 3.用户在使用的时候感觉不出来
七:事务操作
from django.db import transaction
try:
    with transaction.atomic():
        pass  # 多条ORM语句
except Exception as e:
        print(e)
八:模型层常见的字段
字段 功能 AutoField() int类型且自增,必须填入参数 primary_key=True CharField() 主要存储字符串的数据类型 IntegerField() 存储整型数据 BigIntegerField() 大整型,只要用于存储整型的数据 DateField() 主要存储日期类型的数据类型,年月日 DateTimeField() 主要存储日期类型的数据类型,时分秒 DecimalField() 表示固定精度的十进制数的字段。它有两个必须的参数:max_digits:数字允许的最大位数decimal_places:小数的最大位数 EmailField() 邮件格式的数据 BooleanField() 传布尔值存数字0或1 TextField() 存储大段文本 FileField() 存储文件数据 自动找指定位置存储 字段存具体路径 ForeignKey() 外键字段 OneToOneField() 一对一外键字段 ManyToManyField() 多对多外键字段
ORM自定义字段
class MyCharField(models.Field):
    def __init__(self, max_length, *args, **kwargs):
        self.max_length = max_length
        super().__init__(max_length=max_length, *args, **kwargs)

    def db_type(self, connection):
        return char(%s) % self.max_length
info = MyCharField(max_length=32)
九:ORM常见字段参数
字段参数 说明 max_length CharField必须要设置该参数,不然会报错 verboses_name 相当于注释 auto_now 修改一次就重新记录一次此次修改的事件 auto_now_add 只有创建的时候记录,以后不会改变 null 用于表示某个字段可以为空。设置方式:null = True default 为该字段的默认值,设置方式:default = ‘默认值’ max_digits 数字允许的最大位数 decimal_places 小数的最大位数 unique=True 用于表示该字段值在此表中必须是唯一的,建立唯一索引,设置方式:unique = True db_index=True 将该字段设置为索引,设置方式:db_index = True to 绑定外键字段对应的表 to_field 指定想要绑定的外键字段 related_name 给外键字段起别名
choices
当字段数据的可能性可以完全列举出来的时候 应该考虑使用该参数

class UserInfo(models.Model):
        username = models.CharField(max_length=32)
        gender_choice = (
            (1, 男性),
            (2, 女性),
            (3, 其他),
        )
        gender = models.IntegerField(choices=gender_choice)
    userinfo_obj.get_gender_display()
on_delete
参数 功能 models.CASCADE 级联操作,当主表中被连接的一条数据删除时,从表中所有与之关联的数据同时被删除 models.SET_NULL 当主表中的一行数据删除时,从表中所有与之关联的数据的相关字段设置为null,此时注意定义外键时,这个字段必须可以允许为空 models.PROTECT 当主表中的一行数据删除时,由于从表中相关字段是受保护的外键,所以都不允许删除 models.SET_DEFAULT 当主表中的一行数据删除时,从表中所有相关的数据的关联字段设置为默认值,此时注意定义外键时,这个外键字段应该有一个默认值 models.SET() 当主表中的一条数据删除时,从表中所有的关联数据字段设置为SET()中设置的值,与models.SET_DEFAULT相似,只不过此时从表中的相关字段不需要设置default参数 models.DO_NOTHING 什么都不做,一切都看数据库级别的约束,注数据库级别的默认约束为RESTRICT,这个约束与django中的models.PROTECT相似
十:多对多三种表的创建方式
方式一:自动创建
authors = models.ManyTOManyField(to=Author)
优点:第三张表自动创建 缺点:第三张表扩展性差
方式二:手动创建
class Book(models.Model):
    pass
class Author(models.Model):
    pass
class Book2Author(models.Model):
    book_id = models.ForeignKey(to="Book")
    author_id = models.ForeignKey(to="Author")
优点:第三张表扩展性强 缺点:无法使用正反向查询以及多对多四个方法
方式三:半自动创建
class Book(models.Model):
        authors = models.ManyToManyField(to=Author,
                      through=Book2Author
                      through_fields=(book_id,author_id)
                                        )
class Author(models.Model):
     pass
class Book2Author(models.Model):
     book_id = models.ForeignKey(to="Book")
     author_id = models.ForeignKey(to="Author")
优点:扩展性强并且支持正反向查询 缺点:无法使用多对多四个方法
 

标签:公交查询,查询处理,查询器,查询语言,查询方法,查询,查询数据库
来源:

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有