特殊查询常用字段,事务操作

知识提纲

聚合查询
关键字:aggregate
from django.db.models import Max,Min,Count,Sum,Avg

分组查询
    关键字:annotate
    1.最简单的规律
        models后面点什么 就是按什么分组  
    
F与Q查询
    from django.db.modles import F,Q
    F  能够帮助你获取到表中字段所对应的数据
    # 书籍的库存数与卖出数
    models.Book.objects.filter(kucun__gt=F('maichu'))
    
    因为filter过滤的条件的都是and连接 
    modesls.Book.objects.filter(Q(title='python'),Q(price=666))
    modesls.Book.objects.filter(Q(title='python')|Q(price=666))
    modesls.Book.objects.filter(~Q(title='python')|Q(price=666))
    
    # Q进阶用法
    q = Q()
    q.connector = 'or'
    q.children.append(('title','python'))
    q.children.append(('title__icontains','python'))
    q.children.append(('price',666))
    models.Book.objects.filter(q)  # 默认还是and关系  

django中如何开启事务
    from django.db import transaction
    try:
        with transaction.atomic():
            # 事务操作
    except BaseException as e:
        print(e)  

常见字段及参数
    AutoField()
    DateField()
    DateTimeField()
        auto_now
        auto_now_add
    TextField()
    EmailField()          varchar(...)
    BooleanField()        传布尔值  存0/1


自定义char字段
    class MyCharField(models.Field):

        def db_type(self,connection):
            return 'char(%s)'%self.max_length

orm查询优化

    only
    defer

聚合查询

  1. aggregate()是QuerySet的一个终止子句,意思是说,它返回字典.
  2. 键的名称是聚合值得标识符,值是根据聚合函数计算的值,
  3. 键的名称可以自动生出来,也可以向聚合子句提供它.
from django.db.models import Avg,Sum,Max,Min,Count
# 键名称自动的结果为price__avg对应着结果
models.Book.objects.all().aggregate(Avg('price'))

# 向聚合子句提供它
models.Book.objects.all().aggregate(avg_price=Avg('price'))

分组查询

annotate分组依据是前面的值.

示例统计出每个出版社买的最便宜的书的价格.

publisher_list = models.Publisher.objects.annotate(min_price=Min("book__price"))
for obj in publisher_list:
    print(obj.min_price)

    

示例2.统计出每一本书的作者个数

book_list = models.Book.objects.all().annotate(author_num=Count("author"))
for obj in book_list:
    print(obj.author_num)

# 3.统计不止一个作者的图书
"""
1.统计每本书对应的作者个数
2.基于上面的结果 筛选出作者个数大于1 的

"""
res = models.Book.objects.annotate(author_num=Count('authors')).filter(author_num__gt=1).values('author_num')
print(res)

F查询

我们构造的过滤器都只是将字段值和我们设定的某个常量相比较,但是如果想要比较两个字段的值怎么做呢?

不必担心,.Django 就提供了F()来解决这种问题,

F()的实例可以在查询中引用字段,比较同一个model实例中的两个不同的字段的值.

例如查询卖出数大于库存数的商品

from django.db models import F
rest=models.talble_name.objects.filter(maichu__gt=F('kuncun'))
print(rest)

总结:F可以取到表中的字段的对应值当做筛选的一个条件,而不是自定义敞亮的条件了,实现了动态的比较的效果

进阶:Django还支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作,根据表中的数据类型进行数学运算

例如将每个商品的价格都提高50块

models.Product.objects.update(price=F('price')+50)

char字段修改:

利用Concat操作,进行拼接字符串,而且还得加上拼接的值value,位置的参数决定了头部尾部拼接,

from django.db.models.functions import Concat
from django.db.models import Value
ret3=models.Product.objects.update(name=Concat(F('name'),Value('新款')))

Q查询

filter()等方法中逗号隔开的条件是and的关系,如果要变成or的关系就可以使用Q对象,出现Q对象就必须位于关键字参数前面

例如查询卖出数量大于100,价格却小于100元的:

from django.db.models import Q
models.Product.objects.filter(Q(maichu__gt=100)|Q(price__lt=100))

使用方法:用Q包裹条件,|隔开

进阶:&和|操作符以及~操作符
Q对象使用~操作符 就是not的查询

Q查询可以产生对象然后再使用

# q = Q()
# q.connector = 'or'
# q.children.append(('title__icontains','p'))
# # q.children.append(('kucun',666))
# res = models.Book.objects.filter(q)
# print(res)

orm中常见字段

    AutoField(primary_key=True)
    CharField(max_length=32)   varchar(32)
    IntegerField()             int
    BigIntegerField()          long
    DateField()
        auto_now:每次修改数据的时候 都会更新该字段
        auto_now_add:只在创建数据的时候 才会自动将创建时间添加 后续不会再自动修改了
    DecimalField()
    BooleanField(Field)
        - 布尔值类型
        该字段在存储数据的时候 你只需要传布尔值即可
        对应到数据库中 会变成0/1
    TextField(Field)
        - 文本类型
        存大段文本
    EmailField(CharField)               varchar(...)
    FileField(Field)
        - 字符串,路径保存在数据库,文件上传到指定目录
        - 参数:
            upload_to = ""      上传文件的保存路径
            storage = None      存储组件,默认django.core.files.storage.FileSystemStorage

    DecimalField(Field)
    - 10进制小数
    - 参数:
        max_digits,小数总长度
        decimal_places,小数位长度

自定义char字段

    # 自定义char类型字段
    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

Django2.0注意事项

如果你使用的是django2.X版本 你在建数据库表关系的时候
你需要手动指定两个参数
    (你要手动告诉django  级联更新 级联删除  是否建外键约束)
    
    on_delete
    db_constraint

django orm中的事务操作

将sql语句操作变成原子性的操作,要么同时成功,只要有一个失败,就回滚原来的状态,保证数据的完整一致性(NoSQL数据对于事务是部分支持的)

    ACID
        原子性
        一致性
        隔离性
        持久性
        commit
        rollback

    from django.db import transaction
    with transaction.atomic():
        # 在该代码块中所写的orm语句 同属于一个事务
    # 缩进出来之后自动结束

posted @ 2019-10-28 16:16  Huise.J  阅读(142)  评论(0编辑  收藏  举报