ORM的聚合分组F与Q各种查询事务操作

框架基础ORM结束篇

一.聚合查询

from django.db.models import Max, Min, Sum, Avg, Count
1.聚合函数单独使用
  res = models.Book.objects.aggregate(Max('price'),
                                        Min('price'),
                                        Sum('price'),
                                        Avg('price'),
                                        Count('pk')
                                     )
{'price__max': Decimal('29999.88'), 'price__min': Decimal('134.22'), 'price__sum': Decimal('108044.19'), 'price__avg': 15434.884286, 'pk__count': 7}
# 对于没有分组的就是默认整体就是一组
Max  # 统计最大值
Min  # 统计最小值
Sum  # 求和
Avg  # 求某个字段的平均值
Count # 求某个字段的总个数

二.分组查询

1.统计每本书的作者个数
from django.db.models import Count
res = models.Book.objects.annotate(author_num=Count('authors__pk')).values('title', 'author_num')
2.统计每个出版社卖的最便宜的书的价格
res = models.Publish.objects.annotate(min_price=Min('book__price')).values('name', 'min_price')
3.统计不止一个作者的图书
from django.db.models import Count
res=models.Book.objects.annotate(m=Count('authors__pk')).filter(m__gt=1).values('title')
4.统计每个作者出的书的总价格 res=models.Book.objects.annotate(m=Sum('price')).values('authors__name','m')
5.统计每个出版社主键值对应的书籍个数 res=models.Book.objects.values('publish_id').annotate(m=Count('pk')).values('publish__name','m')
# 对于分组用anotate,values写在annotate前则以字段分组,如果卸载annotate后则以表分组

三.F与Q查询

1.对于已有数据表再添加字段需要将字段设置default默认值或者null=Ture或者在迁移命令值直接给默认值
# F查询
from django.db.models import F
2.查询库存大于销量的书籍
res =models.Book.objects.filter(kucun__gt=F('maichu'))
3.将所有数的价格提升1000块
res=models.Book.objects.update(price=F('price')+1000)
4.将所有书的书名加上爆款后缀
from django.db.models.functions import Concat
from django.db.models import Value
res=models.Book.objects.update(name=cancat(F('title'),Value('爆款')))
# Q查询  特点就是可以支持逻辑运算符
1.查询价格大于20000或者卖出大于1000的书籍
res=models.Book.objects.filter(Q(price__gt=2000) | Q(maichu__gt=1000))  # 在Q前加上~就是加上一个not
2.Q对象的进阶用法
q_obj=Q()
q_obj.connector='or'  #默认为and
q_obj.children.append(('price__gt',2000))
q_obj.children.append(('maichu__gt',1000))
res=models.Book.objects.filter(q_obj)
# 对于F查询就是筛选的条件两个都来自表中那么就要用到F查询
# 对于Q查询就是筛选条件是或者的关系就要使用到Q查询

四.ORM查询优化

1.orm查询默认都是惰性查询不用到这个他就不会去做
2.orm默认自带分页功能减轻数据库压力
3.only查询它是将括号内的字段数据全部数据封装到对象中,如果后面查询的不在括号内那么这个时候会去数据库拿
res = models.Book.objects.only('title', 'price')
for obj in res:
    print(obj.title)
    print(obj.price)
    print(obj.publish_time)
4.defer与only用法相反感觉像not only
5.select_related和prefetch_related
  res = models.Book.objects.select_related('publish')
    # for obj in res:
    #     print(obj.title)
    #     print(obj.publish.name)
    #     print(obj.publish.addr)
  select_related括号内只能传一对一和一对多字段,底层原理是连接表,然后将所有数据封装到对象中后续不再走数据库
  prefetch_related底层原理是多次查询到的结果封装到数据对象中,后面查询也不会再走数据库

五.ORM常见字段

1.AutoField()  # 参数primary_key=True必写如果没有这字段会子自动创建自增的主键
2.IntegerField # 整型
3.CharField    # varchar类型必须提供参数max_lengh参数
4.DateField    # 日期字段跟datetime.date
5.DateTimeField # 日期时间字段datetime.datedatetime
6.SmallIntegerField(IntegerField)  # 
7.PositiveSmallIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) # 正小整数 0 ~ 32767
8.IntegerField(Field) # 整数列(有符号的) -2147483648 ~ 2147483647
9.PositiveIntegerField(PositiveIntegerRelDbTypeMixin, IntegerField) # 正整数 0 ~ 2147483647
10.BigIntegerField(IntegerField):# - 长整型(有符号的) -9223372036854775808 ~ 9223372036854775807
11.BooleanField(Field) #  布尔值类型
12.NullBooleanField(Field) # 可以为空的布尔值
13.TextField(Field)  # 文本类型
14.EmailField(CharField) # 字符串类型,Django Admin以及ModelForm中提供验证机制
15.ForeignKey  # 设置一对多关系的外键
16.ManyToManyField # 创建多对多关系的外键
17.OneToOneField  # 创建一对一关系的外键

六.重要参数

1.null=True  # 用于设置字段可以为空
2.unique=True # 设置唯一值
3.db_index=True # 设置索引
4.default='默认值'
5.auto_now_add=True  # 记录数据库创建的时间
6.auto_now=True  # 每次更新数据都会更新时间
7.to   # 设置关联表的表并且会自动跟主键关联
8.on_delete=models.CASCADE # 级联删除
9.db_constraint  # 外键约束

七.事务操作

1.事务四大特性
  原子性
  一致性
  独立性
  持久性
2.简单操作
from django.db import transaction
    try:
        with transaction.atomic():
            pass
    except Exception:
        pass

八.ORM执行原生SQL

# 方式1
from django.db import connection, connections
cursor = connection.cursor()  
cursor = connections['default'].cursor()
cursor.execute("""SELECT * from auth_user where id = %s""", [1])
cursor.fetchone()

# 方式2
models.UserInfo.objects.extra(
                    select={'newid':'select count(1) from app01_usertype where id>%s'},
                    select_params=[1,],
                    where = ['age>%s'],
                    params=[18,],
                    order_by=['-age'],
                    tables=['app01_usertype']
                )

九.多对多三种创建方式

# 全自动(常见)
	orm自动创建第三张表 但是无法扩展第三张表的字段
	authors = models.ManyToManyField(to='Author')
# 全手动(使用频率最低)
	优势在于第三张表完全自定义扩展性高 劣势在于无法使用外键方法和正反向
	class Book(models.Model):
    title = models.CharField(max_length=32)
  class Author(models.Model):
    name = models.CharField(max_length=32)
  class Book2Author(models.Model):
    book_id = models.ForeignKey(to='Book')
    author_id = models.ForeignKey(to='Author')
# 半自动(常见)
	正反向还可以使用 并且第三张表可以扩展 唯一的缺陷是不能用
  add\set\remove\clear四个方法
  
	class Book(models.Model):
      title = models.CharField(max_length=32)
      authors = models.ManyToManyField(
      to='Author',
      through='Book2Author',  # 指定表
      through_fields=('book','author')  # 指定字段
    )
  class Author(models.Model):
       name = models.CharField(max_length=32)
    '''多对多建在任意一方都可以 如果建在作者表 字段顺序互换即可'''
        books = models.ManyToManyField(
      	to='Author',
    	through='Book2Author',  # 指定表
      	through_fields=('author','book')  # 指定字段
    )
  class Book2Author(models.Model):
    book = models.ForeignKey(to='Book')
    author = models.ForeignKey(to='Author')

posted on 2022-05-18 19:44  淦白嫖怪  阅读(65)  评论(0)    收藏  举报

导航