1、F查询:
我们构造的过滤器 filter 只是将字段值与某个我们自己设定的常量做比较。如果需要用到对两个字段来比较,就感觉无从下手了
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
from django.db.models import F,Q
# 当查询条件来自于数据库的某个字段,这个时候就必须使用F
# 查询卖出数大于库存数的商品
res = models.Product.objects.filter(maichu__gt=F('kucun'))
# 将所有商品的价格提高100块
models.Product.objects.update(price=F('price')+100)
# 将所有商品的名字后面加一个爆款后缀
from django.db.models.functions import Concat
from django.db.models import Value
models.Product.objects.update(name=F('name')+'爆款') # 错误示范
models.Product.objects.update(name=Concat(F('name'),Value('爆款')))
注:Concat表示进行字符串的拼接操作,参数位置决定了拼接是在头部拼接还是尾部拼接,Value里面是要新增的拼接值
2、Q查询
filter() 等方法中逗号隔开的条件是与的关系。 如果你需要执行更复杂的查询(例如OR语句),你可以使用Q对象。
# 当你的查询条件想以或的关系查询数据
models.Product.objects.filter(Q(name='变形金刚'),Q(price=999.99)) # 这样写默认还是and关系
models.Product.objects.filter(Q(name='变形金刚')|Q(price=999.99))
# Q与普通过滤条件混合使用
models.Product.objects.filter(Q(name='变形金刚'),price=100.00)
#查询 库存数是100 并且 卖出数不是0 的产品
models.Product.objects.filter(Q(kucun=100)&~Q(maichu=0))
可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。
同时,Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询。
示例3:
查询产品名包含新款, 并且库存数大于60的
models.Product.objects.filter(Q(kucun_gt=60),name_contains='新款')
查询函数可以混合使用Q 对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。
Q查询进阶操作(******)
# 先实例化一个Q对象
q = Q()
q.connector = 'or' #当存在这步操作后,就可以将其默认关系改变为 or
q.children.append(('name','jason')) #name=jason
q.children.append(('price',666)) #price=666
# q对象支持直接放在filter括号内
models.User.objects.filter(q) # q对象默认也是and关系
3、事物
事务的定义:将多个sql语句操作变成原子性操作,要么同时成功,有一个失败则里面回滚到原来的状态,保证数据的完整性和一致性(NoSQL数据库对于事务则是部分支持)
开启事务处理:
try:
with transaction.atomic():
#创建一条订单数据
models.Order.objects.create(num='110',product_id=1,count=1)
#能执行成功
models.Product.objects.filter(id=1).update(kucun=F('kucun')-1,maichu=F('maichu')+1)
except Exception as e:
print(e)
补充:update() 与 save() 的区别:
两者都是对数据的修改保存操作,但是save()函数是将数据列的全部数据项全部重新写一遍,而update()则是针对修改的项进行针对的更新效率高耗时少,所以以后对数据的修改保存用update()
4、only 与 defer
defer('id','name'):取出对象,字段除了id和name都有
only('id','name'):取的对象,只有id和name
res = models.Product.objects.only(id,name)
for i in res:
# 查询不在的字段,会再次查询数据库,造成数据库压力
print(i.name)
5、choice字段
choices字段
class User(models.Model):
name = models.CharField(max_length=32)
password = MyCharField(max_length=32)
choices = ((1,'重点大学'),(2,'普通本科'),(3,'专科'),(4,'其他'))
education = models.IntegerField(choices=choices)
user_obj 是实例化出来的一个对象。
user_obj.education # 拿到的是数字
user_obj.get_education_display() # 固定用法 获取choice字段对应的注释
可见education字段保存了两个信息,一个为数字,一个为对应的注释。