模型层补充

模型层补充

聚合查询

聚合查询就是使用聚合函数
在django里面都封装好了
关键字: aggregate
from django.db.models import Max,Min,Sum,Count,Avg

# 查询所有书的平均价格
res = models.Book.objects.all().aggregate(Avg('price'))

分组查询

关键字: annotate

# 统计每一本书的作者个数
res = models.Book.objects.annotate(author_num = Count('authors')).values('author_num')

# 统计每个出版社最便宜的书的价格
res = models.Publish.objects.annotate(price_min = min(book_price)).values('price_min')

F与Q查询

from django.db.models import F, Q

F查询

其实就是以F('字段名')这种形式,拿到数据库中字段名对应的值

# 查询卖出数量大于库存数量的书籍
res = mdoels.Book.objects.filter(maichu__gt=F('kucun'))
# 把所有的书的价格,全部提高100块
models.Book.objects.filter(price = F('price')+100)
# 尝试在所有的书后面都加上爆款
这个不像数字,字符型是要使用concat拼接的.不然会

Q查询

Q查询也就是可以以Q('字段名=值')这种形式,把数据拿下来之后可以对这种数据进行非或运算,
也就是对条件的处理,F查询是获取对应值

# 查询书籍名称是python或者书籍价格是200的书
res = models.Book.objects.filter(Q(name='python') | Q(price=200))

// ","是and
// "|"是or
// "~"是not

进阶用法

# 还是查询书籍名称是python或者书籍价格是200的书
q = Q()
q.connector = 'or' # 设置q的运算方式
q.children.append('name', 'python')
q.children.append('price', 200)
res = models.Book.object.filter(q)
print(s)


这个可以坐类似于搜索的网页功能
我们知道条件的左边的字段名是不可以使用字符串的,但是我们传递过来的一定是一个字符串
所以我们使用Q查询去把字段名和值条件到Q实例化的对象里面,这样左边的变量名的书写条件就达到了,我们就可以进行我们想要的查询了

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字段

在python的模型层里面有很多django提供的额字段类型,但是如果我们需要不同的,我们就可以自己定义.
例如django里面是没有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.amx_lenth

关于使用django2.x版本

在创建数据库表关系的时候,自己需要手动指定两个参数
(需要手动告诉django 级联更新,级联删除,是否建外键约束)
on_delete
on_constraint

查询优化

only : 根据字段名查询数据,把数据存放到一起,如果只查询该字段的,就无需继续查询数据库,查询其他字段就必须查询数据库
defer : 也是根据字段名查询数据,然后和only相反,查询该字段外的不需要查询数据库,查询该字段就需要继续查询数据库
selete_related :这个是相当于连表查询,就是使用join进行连表查询,只有一句sql语句,并且如果下个表有外键字段就可以一直继续查询,
但是不好的点在于他链接表也是要消耗性能的。
prefetch_related : prefetch_related是要类似于子查询,所以有两条查询语句,他是分别查询两个表,再去用python处理他们之间的关系。
也是可以通过外键字段一直查询。

django orm中的事务操作

事务的特性 - 1.原子性,2.一致性,3.隔离性,4.持久性
事务是要么都成功,要么都失败

# django中怎么使用事务
from django.db import transaction
with transaction.atomic()
'   # 在这个代码块下面所写的orm语句,同属于一个事务
# 缩进出来之后就自动结束

choice参数

1. models.py

class User(models.Model):
    name = models.CharField(max_length=32)
    age = models.IntegerField()
    choice = (       # 这个choice随便取名字,不一定非要choice
        (1, '小学'),
        (2, '初中'),
        (3, '高中')
    )
    edu = models.IntegerField(choice=choice)

在写完上述代码之后,在查询的时候,就可以通过对象.get_指定choice字段名_display()的方式到后面的值,如果没有对应关系时,那么就会取值本身

原文地址:https://www.cnblogs.com/xiongchao0823/p/11752748.html