前言:
Q查询—对对象的复杂查询
F查询–专门取对象中某列值的操作
Q查询
1.Q查询(django.db.models.Q)可以对关键字参数进行封装
,从而更好的封装
from django.db.models import Q
from login.models import New #models对象
news=New.objects.filter(Q(question__startswith='What'))
2.Q对象可以用~操作符放在前面表示否定,也可允许否定与不否定形式的组合
res = models.Book.objects.filter(Q(title="西游记")|~Q(publish_id=2))
print(res)
3.Q查询可以让filter过滤实现或的条件使用|
res = models.Book.objects.filter(Q(title="西游记")|Q(publish_id=2))
print(res)
4.应用范围组合查询:
res = models.Book.objects.filter(
Q(title="西游记"),
Q(publish_id=2)|Q(publish_time="2019-06-13"))
print(res)
等价于
select *from where title ="西游记" and(publish_id=2 orpublish_time="2019-06-13")
5.Q对象可以与关键字参数查询一起使用,不过一定要把Q对象放在关键字参数查询的前面
正确:
models.Book.objects.filter(
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)),
question__startswith='Who')
错误:
Poll.objects.get(
title="西游记",
Q(publish_id=2)|Q(publish_time="2019-06-13"))
F查询:
F查询–专门取对象中某列值的操作
F本质是是列操作:
看如下示例:
当我们要查询销量大于库存的商品时,就要使用F查询了:
销售与剩余的分别是一列:因此用F查询再好不过了
from django.db.models import F,Q
# F查询
res = models.Product.objects.filter(sell__gt=F(‘stock’))
print(res)
同样我们可以将某列的值进行增减对价格:
from django.db.models import F
models.Book.objects.update(price= F("price")+10)
ORM不支持+拼接字符串,mysql中我们拼接字符串要用concat,此处同理:
# 要进行字符串的拼接需要先导入Concat和Value模块
from django.db.models.functions import Concat
from django.db.models import Value
models.Product.objects.update(name=Concat(F('name'), Value('爆款')))
事务
事务的四大特性:
Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成 功,要么全部失败。
Consistency(一致性):事务完成时,数据必须处于一致状态,数据的完整性约束没有被破坏,事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没 有执行过一样。
Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性 和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。
Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。
事务的语法
在sql语句中使用事务时,我们需要用start开启事务,又要用end结束事务,这就需要我们判断事务何时开始和结束比较好。而在Django的ORM中,直接使用上下文管理即可,省事又省心。
这里直接拿上面提到过的销售表做示例,比如一件商品卖出后,销量要+1,对应的库存要-1。
from django.db import transation
from django.db.models import F
with transaction.atomic():
models.Product.objects.filter(id=1).update(stock=F("stock")-1)
models.Product.objects.filter(id=1).update(price=F("price")+1)
only和defer
only和defer返回的是列表套对象的QuerySet对象,有点类似filter()和exclude()的类似,包含与不包含
# 输出一下用values取出来的结果(列表套字典,键为'name')
test = models.Product.objects.values('name')
print(test)
# only取出来的是列表套对象,对象只有name属性
res = models.Product.objects.only('name')
for i in res:
print(i.name)
# defer取出来的是列表套对象,对象除了name属性,其他属性都有
res1 = models.Product.objects.defer('name')
for i in res:
print(i.name)
自定义字段:
Django支持自定义字段,需要继承models.Field类
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,connnection):
return 'char(%s)'%self.max_length
字段中的choice属性:
当我们给一个表新增一个字段时,如果表中已经有数据了,那么我们可以将models.py中新增的字段名null设置默认值或者是设置为空。
gender = models.IntegerField(default=2)
允许为空:
gender= models.CharField(null=True)
choices属性使用的场景也挺多,比如性别,在数据库中我们可以存储数字,比如1代表男,2代表女,而显示给用户看时,要转变为对应的男或女
示例:
class User(models.Model):
name = models.CharField(max_length=32)
choice = ((1,"男"),(2,"女"))
gender = models.IntegerField(choices = choices,default=2)
```
这样数据库存的就是数字,怎么取出来如下:
res = models.User.objects.filter(id = 1).first()
print(res.gender)
#获取编号对应的中文注释,固定写法get_字段名_display()
print(res.get_gender_display())
创建对象时任然传数字
models.User.objects.create(name='wy',gender=1)