F查询
在上面所有的例子中,我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
示例1:
查询出卖出数大于库存数的商品
from django.db.models import F
ret1=models.Product.objects.filter(maichu__gt=F('kucun'))
print(ret1)
F可以帮我们取到表中某个字段对应的值来当作我的筛选条件,而不是我认为自定义常量的条件了,实现了动态比较的效果
Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。基于此可以对表中的数值类型进行数学运算
将每个商品的价格提高50块
models.Product.objects.update(price=F('price')+50)
引申:
如果要修改char字段咋办(千万不能用上面对数值类型的操作!!!)?
如:把所有书名后面加上'新款',(这个时候需要对字符串进行拼接Concat操作,并且要加上拼接值Value)
from django.db.models.functions import Concat
from django.db.models import Value
ret3=models.Product.objects.update(name=Concat(F('name'),Value('新款')))
Concat表示进行字符串的拼接操作,参数位置决定了拼接是在头部拼接还是尾部拼接,Value里面是要新增的拼接值
Q查询
filter() 等方法中逗号隔开的条件是与的关系。 对象。
示例1:
查询 卖出数大于100 或者 价格小于100块的
from django.db.models import Q models.Product.objects.filter(Q(maichu__gt=100)|Q(price__lt=100))
对条件包裹一层Q时候,filter即可支持交叉并的比较符
示例2:
查询 库存数是100 并且 卖出数不是0 的产品
models.Product.objects.filter(Q(kucun=100)&~Q(maichu=0))
我们可以组合& 和| 操作符以及使用括号进行分组来编写任意复杂的Q 对象。
NOT) 查询。
示例3:
查询产品名包含新款, 并且库存数大于60的
models.Product.objects.filter(Q(kucun__gt=60), name__contains="新款")
查询函数可以混合使用Q 对象和关键字参数。Q 对象,它必须位于所有关键字参数的前面。
事务
事务的定义:将多个sql语句操作变成原子性操作,要么同时成功,有一个失败则里面回滚到原来的状态,保证数据的完整性和一致性(NoSQL数据库对于事务则是部分支持)
# 事务
# 买一本 跟老男孩学Linux 书
# 在数据库层面要做的事儿
# 1. 创建一条订单数据
# 2. 去产品表 将卖出数+1, 库存数-1
from django.db.models import F
from django.db import transaction
# 开启事务处理
try:
with transaction.atomic():
# 创建一条订单数据
models.Order.objects.create(num="110110111", 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)
其他鲜为人知的操作
Django ORM执行原生SQL
条件假设:就拿博客园举例,我们写的博客并不是按照年月日来分档,而是按照年月来分的,而我们的DateField时间格式是年月日形式,也就是说我们需要对从数据库拿到的时间格式的数据再进行一次处理拿到我们想要的时间格式,这样的需求,Django是没有给我们提供方法的,需要我们自己去写处理语句了
# extra # 在QuerySet的基础上继续执行子语句 # extra(self, select=None, where=None, params=None, tables=None, order_by=None, select_params=None) # select和select_params是一组,where和params是一组,tables用来设置from哪个表 # Entry.objects.extra(select={'new_id': "select col from sometable where othercol > %s"}, select_params=(1,)) # Entry.objects.extra(where=['headline=%s'], params=['Lennon']) # Entry.objects.extra(where=["foo='a' OR bar = 'a'", "baz = 'a'"]) # Entry.objects.extra(select={'new_id': "select id from tb where id > %s"}, select_params=(1,), order_by=['-nid']) 举个例子: models.UserInfo.objects.extra( select={'newid':'select count(1) from app01_usertype where id>%s'}, select_params=[1,], where = ['age>%s'], params=[18,], order_by=['-age'], tables=['app01_usertype'] ) """ select app01_userinfo.id, (select count(1) from app01_usertype where id>1) as newid from app01_userinfo,app01_usertype where app01_userinfo.age > 18 order by app01_userinfo.age desc """ # 执行原生SQL # 更高灵活度的方式执行原生SQL语句 # from django.db import connection, connections # cursor = connection.cursor() # cursor = connections['default'].cursor() # cursor.execute("""SELECT * from auth_user where id = %s""", [1]) # row = cursor.fetchone()