模型层补充
聚合查询
聚合查询就是使用聚合函数
在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()
的方式到后面的值,如果没有对应关系时,那么就会取值本身