django模型层ORM补充
目录
模型层ORM补充
ORM在操作数据对象之前可以先对其进行拦截操作
# 模型表:
class User(models.Model):
name = CharField(max_length=32)
# ......
def save(self):
# ......
supper().save()
def delete(self):
# ......
super().delete()
F查询和 Q查询
models.py文件内容准备
class Product(models.Model):
name = models.CharField(max_length=32) # 都是类实例化出来的对象
price = models.DecimalField(max_digits=8,decimal_places=2)
maichu = models.IntegerField()
kucun = models.IntegerField()
info = MyCharField(max_length=32,null=True) # 改字段可以为空
choices = ((1,'男'),(2,'女'),(3,'其他'))
gender = models.IntegerField(choices=choices,default=2)
F查询
寻常的查询都只是将字段值与某个我们自己设定的常量做比较,如果要对两个字段的值作比较,该怎么做呢?
Django提供F()来做这样的比较,F()的实例可以在查询中引用字段,来比较同一个model实例中两个不同字段的值
# 查询卖出数大于库存数的商品
from django.db.models import F
res = models.Product.objects.filter(maichu__gt=F("kucun"))
F()可以帮我们取到表中某个字段对应的值来当做我的筛选条件,而不是我人为自定义常量的条件了,这样子就实现了动态比较的效果
Django支持F()对象之间以及F()对象和常数之间的加减乘除和取模的操作,基于此可以对表中的数值类型进行数学运算
# 将每个商品的价格提高50元
models.Product.objects.update(prince=F("price")+50)
补充:如果要修改字符串字段的话,千万不能用+来做字符串拼接
# 把书名后面加上"爆款"两字,(这时需要对字符串进行拼接Concat操作,并且要加上拼接值Value)
from django.db.models.functions import Concat
from django.db.models import Value
res = models.Product.objects.update(name=Concat(F("name"), Value("爆款")))
# Concat标识进行字符串的拼接操作,参数位置决定了拼接是在头部拼接还是尾部拼接,Value里面是要新增的拼接值
Q查询
filter()等方法中逗号隔开的条件是与(and)关系,如果你需要执行更复杂的查询(例如:or 语句),你可以使用Q对象
# 查询 卖出数大于100 或者 价格小于100块的
from django.db.models import Q
models.Product.objecet.filter(Q(maichu__gt=100)|Q(price__lt=100))
对象包裹一层Q时,filter即可支持交叉并的比较符
# 查询 库存数是100 并且 卖出数不是0的产品
models.Product.objects.filter(Q(kucun=100)&~Q(maichu=100))
查询函数可以混合使用Q对象和关键字参数,所有提供给查询函数的参数(关键字参数或Q对象)都将"AND"在一起,如果出现Q对象,他必须位于所有关键字参数前面
事务
事务的定义:将多个sql语句操作变成原子性操作,要么同时成功,有一个失败则回滚到事务之前的阶段,可以保证数据的完整性和一致性(NoSQL数据对事务则是部分支持)
# 事务的ACID
原子性
一致性
隔离性
持久性
# 事务:
# 买一本 书 需要在数据库中做的事情:
# 1、创建订单数据
# 2、去 产品表 将 卖出数+1 库存数-1
from django.db.models import F
from django.db import transaction
# 开启事务处理
try:
with transaction.atomic():
# 创建一条订单数据
models.Order.objects.create(num="11011101001", product_id=1,count=1)
# 能执行成功
models.Product.objects.filter(id=1).update(kucun=F("kucun")-1, maichu=F("maichu"+1)
except Execption as e:
print(e)
几个比较重要的方法:
update()与save()的区别
两者都是对数据的修改保存操作,但是save()函数是将数据列的全部数据项全部重新写一遍,而update()则是针对修改的项进行针对的更新,效率高耗时少
所以以后对数据的修改用update()
only与defer
# 拿到的是一个对象 两者是相反的
res = models.Product.objects.values('name') # 这样子拿到的对象是有所有字段数据的
res = models.Product.objects.only('name') # 这样子拿到的对象只有name字段的数据
res = models.Product.objects.defer('name') # 这个拿到的对象除了name字段,其他字段全都有
for i in res:
print(i.name)
choices
# models.py写法
class Product(models.Model):
choices = ((1,"男"),(2,"女"),(3,"保密"))
gender = models.IntegerField(choices=choices,default=3)
# 后端查看该choices字段值的方法:
res = models.Product.objects.filter(id=1).first()
print(res.gender) # 1
print(res.get_gender_display()) # 男 # 可以获取到编号对应的中文注释
models.Products.objects.create(..., gender=1) # 新增该字段是直接传数字即可

浙公网安备 33010602011771号