django之 F与Q查询
Posted huangxuanya
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了django之 F与Q查询相关的知识,希望对你有一定的参考价值。
F与Q查询
F查询
why???????
我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?
answer:Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。
show time (我们来演示以下啪)???
1 from django.db import models 2 3 # Create your models here. 4 5 class Product(models.Model): 6 name=models.CharField(max_length=32) 7 price = models.DecimalField(max_digits=8, decimal_places=2) 8 sell = models.IntegerField() 9 stock = models.IntegerField() 10 11 def __str__(self): 12 return ‘商品对象的名字:%s‘ %(self.name)
1 # 将所有的商品的价格提高100块 2 models.Product.objects.update(price=F(‘price‘)+100) 3 4 5 update是批量操作,作用于每一个叫price的字段? 6 注意:??? 7 1.将价格提高是个更新的操作 8 2.update是没有返回值的 9 3.update必须要写指定一个变量名price=... 10 4.价格提高一百,首先考虑将价格字段找出来
结论:Django 支持 F() 对象之间以及 F() 对象和常数之间的加减乘除和取模的操作。基于此可以对表中的数值类型进行数学运算????
如果要修改char字段咋办(千万不能用上面对数值类型的操作!!!)????
1 # 将所有商品的名字后面都加一个爆款 2 from django.db.models.functions import Concat 3 from django.db.models import Value 4 models.Product.objects.update(name=Concat(F(‘name‘),Value(‘爆款‘)))
结论:把所有name后面加上‘爆款‘,(这个时候需要对字符串进行拼接Concat操作,并且要加上拼接值Value),
Concat表示进行字符串的拼接操作,参数位置决定了拼接是在头部拼接还是尾部拼接,Value里面是要新增的拼接值
Q查询
导火线:??
1 hhh=models.Product.objects.filter(price=188.88,name=‘连衣裙爆款‘) 2 print(hhh) 3 4 5 结果: 6 <QuerySet []> 7 8 结论:filer是过滤 (条件一and条件2) 9 10 不成立,返回空的queryset对象
1 from django.db.models import Q 2 # and 关系 3 one = models.Product.objects.filter(Q(price=188.88),Q(name=‘连衣裙爆款‘)) 4 # or 关系 5 two = models.Product.objects.filter(Q(price=188.88)|Q(name=‘连衣裙爆款‘)) 6 # not 关系 (价格是488.88,衣服的名字不是连衣裙爆款的条件) 7 three = models.Product.objects.filter(Q(price=488.88)|~Q(name=‘连衣裙爆款‘)) 8 print(one, two, three)
结论:如果有多个筛选条件,而filter只能是and的关系,所以可以考虑使用Q对象,| 是or 的关系,|~是not 取反的关系
注意:???
Q(表中的字段=‘.....‘)
1 # 混合使用 需要注意的是Q对象必须放在普通的过滤条件前面 2 #and 名字为‘高跟鞋爆款‘,并且价格为488.88 3 mixture1 = models.Product.objects.filter(Q(name=‘高跟鞋爆款‘),price=488.88) 4 print(mixture1) 5 #mot取反 名字不为‘高跟鞋爆款‘,并且价格为488.88 6 mixture2 = models.Product.objects.filter(~Q(name=‘高跟鞋爆款‘), price=488.88) 7 print(mixture2)
补充小知识点:
1 from django.db.models import F,Q 2 q=Q() 3 # 通过这个参数可以将Q对象默认的and关系变成or 4 q.connector = ‘or‘ 5 q.children.append((‘price‘,923.34)) 6 #append说明是list,所以可以追加第二个元素 7 q.children.append((‘name‘,‘高跟鞋爆款爆款爆款爆款爆款‘)) 8 lalala = models.Product.objects.filter(q) # Q对象查询默认也是and ,这里变成了or 9 print(lalala)
Q与F查询需要注意的点????
1.F与Q查询都是在filter ,update等中使用, 2. res = models.表名.objects.filter(字段名1__gt=F(‘字段名2‘)) 表示字段名1大于字段名2 必须是数字类型比较 ???? res=models.表名.objects.update(字段名1=F(‘字段名1‘)+100) 数字进行相加,update遍历运算 ???? res=models.表名.objects.update(字段名1=Concat(F(‘字段名1‘),Value(‘自定义的字符串‘))) 字段的值必须也是字符串,字符串相加 ???????????????????????????????????? 3. res=models.表名.objects.filter(Q(字段名1=字段对应的值为整型)|~Q(字段名2=‘字段对应的值为字符串类型加引号‘)) ?? res = models.表名.objects.filter(~Q(字段名1=‘字段值字符串类型‘),字段名2=字段值为整型) ?? from django.db.models import F, Q q = Q() q.connector = ‘or‘ # 通过这个参数可以将Q对象默认的and关系变成or q.children.append((‘字段名1‘,字段值整型)) q.children.append((‘字段名2‘,‘字段值字符串‘)) res = models.表名.objects.filter(q) # Q对象查询默认也是and print(res)
事务
事务的定义:将多个sql语句操作变成原子性操作,要么同时成功,有一个失败则里面回滚到原来的状态,保证数据的完整性和一致性(NoSQL数据库对于事务则是部分支持)
原子性??
一致性??
隔离性??
持久性??
1 # 将卖出数 + 1, 库存数 - 1 2 from django.db import transaction 3 from django.db.models import F 4 try: 5 with transaction.atomic(): 6 # 在with代码块儿写你的事务操作 7 models.Product.objects.filter(id=1).update(sell=F(‘sell‘)-1) 8 models.Product.objects.filter(id=1).update(stock=F(‘stock‘)+1) 9 # # 写其他代码逻辑 10 except Exception as e: 11 print(e)
orm字段补充
only与defer
1 aaa = models.Product.objects.values(‘name‘) #列表套字典 2 print(aaa) 3 # <QuerySet [‘name‘: ‘高跟鞋爆款‘, ‘name‘: ‘连衣裙爆款‘, ‘name‘: ‘帽子爆款‘]> 4 res = models.Product.objects.only(‘name‘) #only能够帮你拿到对象 5 print(res) 6 #<QuerySet [<Product: 商品对象的名字:高跟鞋爆款>, <Product: 商品对象的名字:连衣裙爆款>, <Product: 商品对象的名字:帽子爆款>]> 7 for i in res: #走了一句sql语句,对象中存在这个字段 8 print(i.name) 9 # 高跟鞋爆款 10 # 连衣裙爆款 11 # 帽子爆款 12 for i in res: #走了四句sql语句 (包括models.Product.objects.only(‘name‘)这一句) for循环三次(数据库三个name),所以是四次 13 print(i.price) #only得到的对象去点一个没有的字段,可以点但是会重新走一遍sql语句,效率低 14 15 16 defer = models.Product.objects.defer(‘name‘) 17 print(defer) 18 # < QuerySet[ < Product: 商品对象的名字:高跟鞋爆款 >, < Product: 商品对象的名字:连衣裙爆款 >, < Product: 商品对象的名字:帽子爆款 >] > 19 for i in res: #走一次sql语句,有这个字段 20 print(i.price) 21 # 888.88 22 # 2688.88 23 # 923.34 24 for i in res: #走四次sql语句 没有这个字段 25 print(i.name)
only是name查对象,里面只有name属性,defer是name查对象,除了name属性,其他的都有??????
gender
1 gender = models.Product.objects.filter(id=1).first() 2 print(gender.gender) #展示的是数字 3 print(gender.get_gender_display()) #获取编号对应的中文注释choices = ((1,‘男‘),(2,‘女‘),(3,‘其他‘)) 4 models.Product.objects.create(gender=1) 5 6 #传数据的时候只要存数字,查的时候就用.get_gender_display()
以上是关于django之 F与Q查询的主要内容,如果未能解决你的问题,请参考以下文章