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)  # 新增该字段是直接传数字即可
posted @ 2019-06-13 16:42  输诚  阅读(118)  评论(0)    收藏  举报