DjangoORM操作之其他知识点
一、F与Q查询
F查询
F查询的应用场景主要是当你想要查询字段需要与数据库中的另外一个字段进行比较的时候,基于我们前面所学的知识点无法完成,那就需要用到F查询。
F的导入
from django.db.models import F,Q
F查询的使用
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() def __str__(self): return '这是商品:%s'%self.name
基于models表做的几个F查询的练习
#查询卖出数大于500的商品 res = models.Product.objects.filter(maichu__gt=500) print(res) from django.db.models import F,Q # 查询卖出数大于库存数的商品 res = models.Product.objects.filter(maichu__gt=F('kucun')) print(res) #查询卖出数小于库存数 res = models.Product.objects.filter(maichu__lt=F('kucun')) print(res) #将所有的商品的价格提高100块 res = models.Product.objects.update(price=F('price')+100) print(res)
其实通过上面的练习,你也发现了F查询的本质其实就是给你一个字符串形式的字段,你可以直接拿出这个字段在数据库中存储的值,然后可以对拿到的这个值进行操作。和其他字段值的比较,将当前字段的值全部加100等...但是,如果想让你给当前的字段加一个后缀,怎么实现呢?这还不简单,来,看我秀!
#将所有的商品后面都加上一个爆款 models.Product.objects.update(name=F('name')+'爆款')
然后一执行,哎呀,怎么回事,小老弟,怎么会这样
再次尝试
bug原因如下
第一步:
第二步:
么有刷新数据库,直接执行了正确的操作,就会变成上面的结果👆👆👆
最终正确的方案,虽然没什么惊喜了,但是还是来low一眼吧🤦🤦🤦
Q查询
F主要是用于查询数据库中的另外一个字段,那么你有没有发现,我们每次查询他的filter里面的参数都是and的关系,但是我们又不想每次都是and,就算是咸鱼久了还要翻身呢吧,那我们实际查询的时候改变字段的关系就得用到这个新的知识点了,Q查询
Q查询的一些小练习
or
not
Q对象补充(*****)
当外界获取用户那边输入的是一个字符串,可以获取数据库里面的值
#Q对象的补充(****) from django.db.models import F,Q q=Q() q.connector='or' #通过这个参数可以将q对象默认的and关系变成or q.children.append(('price',199)) #外界传来的是一个字符串的形式 q.children.append(('name','丝袜爆款')) res = models.Product.objects.filter(q) #支持直接将q丢进去 print(res)
二、事务
1.事务的四大特性:
Atomic(原子性):事务中包含的操作被看做一个逻辑单元,这个逻辑单元中的操作要么全部成 功,要么全部失败。
Consistency(一致性):事务完成时,数据必须处于一致状态,数据的完整性约束没有被破坏,事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没 有执行过一样。
Isolation(隔离性):事务允许多个用户对同一个数据进行并发访问,而不破坏数据的正确性 和完整性。同时,并行事务的修改必须与其他并行事务的修改相互独立。
Durability(持久性):事务结束后,事务处理的结果必须能够得到固化。
2.django事务的使用
在数据库中使用事务的时候,我们必须使用start开启事务,但是在django中支持直接开始事务,事务的开启用的是with
from django.db import transaction
事务的开启
from django.db import transaction with transaction.atomic(): #再这里写数据库操作
from django.db import transaction from django.db.models import F with transaction.atomic(): models.Product.objects.filter(id=1).update(kucun=F('kucun')-1) models.Product.objects.filter(id=1).update(maichu=F('maichu')+1)
三、自定义字段
因为django是不支持char类型的,但是支持我们自定义字段,具体实现看下面的代码
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): return 'char(%s)'%self.max_length class User(models.Model): name=models.CharField(max_length=32) password=MyCharField(max_length=32)
四、only与defer
only与defer两者是相反的,拿到的都是一个对象,对于only来说,如果后面你要查询的字段是指定的字段的话,就会只走一次数据库,其他字段就会走四次数据库,但是defer是与他们刚好相反,查当前指定字段的话就会走四次数据库,其他数据就会只走一次数据库
# only与defer 拿到的是一个对象 两者是相反的 res = models.Product.objects.values('name') res1 = models.Product.objects.only('name') res2 = models.Product.objects.defer('name') for i in res: print(i.name)
五、choices字段(**)
主要是用于存储信息的时候,选择的不同数据对应到不同的内容,然后给用户看的是内容,数据库中存的是数字
choices字段 #涉及到选择选择相关的,都有的是choices字段 class User(models.Model): name=models.CharField(max_length=32) password=MyCharField(max_length=32) choices=((1,'重点大学'),(2,'普通本科'),(3,'专科'),(4,'其他'),(),()) education = models.IntergeField(choices=choices) #有这个参数 user_obj.education #拿到的是数字 user_obj.get_education_display() #固定用法,获取choices字段对应的注释