Django 之 F查询与Q查询,事务与其他

   一、F查询与Q查询(Django模块)需要导入(********)当你的条件来自于数据哭的时候优先考虑F与Q查询 在考虑你所学的查询方法()

  1.1 F查询:

    作用:操作数据表中的某列值,F()允许Django在未实际链接数据的情况下具有对数据库字段的值的引用,不用获取对象放在内存中再对字段进行操作,直接执行原生产sql语句操作。

 通常情况下我们在更新数据时需要先从数据库里将原数据取出后方在内存里,然后编辑某些属性,最后提交。

 

在上面所有的例子中,我们构造的过滤器都只是将字段值与某个我们自己设定的常量做比较。如果我们要对两个字段的值做比较,那该怎么做呢?

Django 提供 F() 来做这样的比较。F() 的实例可以在查询中引用字段,来比较同一个 model 实例中两个不同字段的值。

示例1:

查询出卖出数大于库存数的商品

# Create your tests here.
if __name__ == "__main__":
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "day60test.settings")
    import django
    django.setup()
    from app01 import models
    # 前提是要导入这个F与Q
    from django.db.models import F,Q
    # 为什么需要F与Q查询
    # 前面的filter里面都是用字段与一个常量比较,之前的数据都是我看根据表手动添加现在查询记录
    # 如果要比较的是两个字段呢,就需要借助F函数了 
    # 1. 查询卖出数大于库存数的商品
    res1 = models.Product.objects.filter(maichu__gt=F('kucun'))
    print(res1) 
    # 拿到卖出大有库存的对象 <QuerySet [<Product: 商品对象的名字:上衣>, <Product: 商品对象的名字:裤子>]>

 


# F实列2.将所有的商品价格提高100块
res2 = models.Product.objects.update(price=F('price')+100)
print(res2)

 

 

# 3.将所有的名字后面加上一个爆款后缀 需要导入Concat
from django.db.models.functions import Concat # 字符串拼接(*****)
from django.db.models import Value
res = models.Product.objects.update(name=Concat(F('name'),Value('爆款')))

 

 
 

 

 

  1.2 Q查询:

filter() 等方法中逗号隔开的条件是与的关系。 如果你需要执行更复杂的查询(例如ORM语句),你可以使用Q对象

示例1:

# 当你的查询条件想以and |或的关系查询数据是
res = models.Product.objects.filter(Q(name='上衣爆款爆款'),Q(price=299))
print(res) # and必须是同时满足才能进行查取 不然得到结果为空

# ,是and 的关系 必须同时满足 两个条件 那么或怎么查呢
# res1 = models.Product.objects.filter(Q(name='上衣爆款爆款')|Q(price=21088))
# print(res1)
# 或是只要有一方Q(name=)或者Q(price=) 都可以查到我们的目标对象 要么都没 要么都有 要一方有

   

注意:Q与普通过滤条件混合使用 需要注意Q(过滤条件必须在前面)必须
modles.Ptoduct.objectsfilter(Q(name='上衣’),price=199)
# Q查询进价操作(*****)为什用Q查询 应为filter() 是and并列关系 Q可以and 也可以or 更加灵活
# 第一 先实列化一个Q对象
q = Q()
q.connector = 'or' # 里面是默认and关系 这里是将q.children.appen('name','jason') 注意里面是字符串
q.children.append(('name','jason'))
q.children.append(('price', 666)) # 那最终还是and 的关系 所以需要加上面的q.connector= ‘or’ 就是或的查询关系
res = models.Product.objects.filter(q)
print(q) # q对象样式默认关系
# (or: ('name', 'jason'), ('price', 666))

二、 事务
2.1 什么是事务:开启一个事物可以包含一些SQL语句,这些语句要么同时成功,要么一个都别想成功,
  称之为事务的原子性
2.2 为什么用事务:保障对数据的安全性 。
思考如何保障:
2.3 事务的四大特性(A C I D):
  原子性(atomicity):一个事务是一个不可以分割的工作单位,事务包括诸多操作,要么都执行,要么都不执行。
  
  一致性(consistency):事务必须是数据库从一个一致性状态变到另一个一致性状态。一致性与原子性是精密相关的。

隔离性(isolation):一个事务的执行不能被其他事务干扰,指的是:一个事务内部的操作及使用的数据对并发的其他事务是隔离的,并发执行
              的各个事务之间不能相互干扰。

持久性(durability):也称之为(permanence):只一个人事务一旦提交,他对于数据库的改变的永久性的,接下来的操作
或故障不会对其产生任何影响。
之前的用法:
2.4 怎么用:
之前的用法:开启事务》》start transaction (操作数据update..) >>一旦一方出错可以回滚到起始位rollback
>>开启事务之后,只要没有进行commit 操作,数据并不会真正刷硬盘上。》》确认数据操作无误执行commit
操作。保存事务状态和数据的一致性和安全性
# 修改数据之前先开启事务操作
start transaction;

# 修改操作
update user set balance=900 where name='wsb'; #买支付100元
update user set balance=1010 where name='egon'; #中介拿走10元
update user set balance=1090 where name='ysb'; #卖家拿到90元

# 回滚到上一个状态
rollback;

# 开启事务之后,只要没有执行commit操作,数据其实都没有真正刷新到硬盘
commit;
"""开启事务检测操作是否完整,不完整主动回滚到上一个状态,如果完整就应该执行commit操作"""

# 站在python代码的角度,应该实现的伪代码逻辑,
try:
    update user set balance=900 where name='wsb'; #买支付100元
    update user set balance=1010 where name='egon'; #中介拿走10元
    update user set balance=1090 where name='ysb'; #卖家拿到90元
except 异常:
    rollback;
else:
    commit;
View Code

  教你事务怎么用其实相当的简单|:

  from Django.db import transacton 

  from Django.db.models import F   # F 字段查询--修改具体值

  with transaction atomic():

    # 执行相关sql 语句操作

    modles.Product .objects.filter(id=1).update(kucun=F('kucun)-100)

    modles.Product.objects.filter(id=1).update(maichu=F('maichu')+100)

  # 直接写其他代码就可以了 完成事务操作  可以直接出事务了

    with transaction.atomic():   # 事务的原子性:同进同出
        # 里面开始写执行条件代码块及操作
        # sql语句 执行数据的更新              更新的内容是:kuncun=F('查询')加减乘除
        models.Product.objects.filter(id=1).update(kucun=F('kucun')-100)
        models.Product.objects.filter(id=1).update(maichu=F('maichu')+100)
    # 那么什么时候是确认退出
    # 出到与with平行可以直接写其他代码 执行完毕
    print('直接出来写其他代码上述已完成对数据库的事务操作')

 


执行事务后

 

事务遵循的四大特性:ACID 原子性 增删改查 一方执行 另一方同步进行

from django.db import transaction
with transaction.atomic():
# 这里写多个数据库操作
print('其他逻辑代码')

 三、 自定义字段类型

自定义字段类型:如

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, connection):
        # 需要返回一个char类型的字段
        return 'char(%s)'% self.max_length

 

 

 

class Product(models.Model):
    price = models.DecimalField(max_digits=8,decimal_places=2,default=0)
    name = models.CharField(max_length=32)   # 这是类实例化出来的对象
    maichu = models.IntegerField()
    kucun = models.IntegerField()
    info = models.IntegerField(max_length=32,default=0)   # 当改字段可以设为空
    message = MyCharField(max_length=32,null=True) # 必须加默认值  # 自定义MyCharField 帮我们创建retuan char
    # choice = ((1, '男'),(2,'女'), (3,'其他'))      #补充:新增字段default 或者Null 都可以看情况

    def __str__(self):
        return '商品对象的名字:%s'%self.name

 

四、only与defer拿到的是一个对象: 有什么用:

# only 的用法
    res = models.Product.objects.only('name')
    print(res)
    for i in res:
        print(i.name)

<QuerySet [<Product: 商品对象的名字:帽子爆款爆款>, <Product: 商品对象的名字:上衣爆款爆款>, <Product: 商品对象的名字:裤子爆款爆款>]>
帽子爆款爆款
上衣爆款爆款
裤子爆款爆款

总结:相当于noly 查询出来的res对象里包含了所有属性 可以通过i.name 或i.price属性直接获取值 没有必要重新走数据库 好处在于》》》

   不会频繁的走数据库,拖慢数据库,避免对数据造成压力提高效率,节约查询时间

 

defer:

(0.000) SELECT `app01_product`.`id`, `app01_product`.`price`, `app01_product`.`maichu`, `app01_product`.`kucun`, `app01_product`.`info`, `app01_product`.`message` FROM `app01_product`; args=()
(0.001) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 1; args=(1,)
(0.000) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 2; args=(2,)
帽子爆款爆款
上衣爆款爆款
裤子爆款爆款
(0.001) SELECT `app01_product`.`id`, `app01_product`.`name` FROM `app01_product` WHERE `app01_product`.`id` = 3; args=(3,)

  print(i.name) 相当于走了四次

(0.000) SELECT @@SQL_AUTO_IS_NULL; args=None
(0.000) SELECT VERSION(); args=None
(0.000) UPDATE `app01_product` SET `kucun` = (`app01_product`.`kucun` - 100) WHERE `app01_product`.`id` = 1; args=(100, 1)
(0.000) UPDATE `app01_product` SET `maichu` = (`app01_product`.`maichu` + 100) WHERE `app01_product`.`id` = 1; args=(100, 1)
(0.000) SELECT `app01_product`.`id`, `app01_product`.`price`, `app01_product`.`maichu`, `app01_product`.`kucun`, `app01_product`.`info`, `app01_product`.`message` FROM `app01_product`; args=()
直接出来写其他代码上述已完成对数据库的事务操作
188.99
299.00
2088.00

  print(i.price) 上面只走了一次  速度相当的快 相当于对于自己的查询正向查询反而慢 

五、update() yu save()

  update()与save()的区别

  两者都是对数据的修改保存操作,但是save()函数是将数据列的全部数据项全部重新写一遍,而update()则是针对修改的项进行针对的更新效率高耗时少

  所以以后对数据的修改保存用update()

 



六、 choices= choices 字段

class Product(models.Model):
    price = models.DecimalField(max_digits=8,decimal_places=2,default=0)
    name = models.CharField(max_length=32)   # 这是类实例化出来的对象
    maichu = models.IntegerField()
    kucun = models.IntegerField()
    info = models.IntegerField(max_length=32,default=0)   # 当改字段可以设为空
    message = MyCharField(max_length=32,null=True)

    choices = ((1, '男'),(2,'女'), (3,'其他'))
    gender = models.IntegerField(choices=choices,default=2)   # 注意了哈

  

 

 

六、choices字段
#choices 字段固定语法
res = models.Product.objects.filter(id=1).first() # 注意这是拿到对象
print(res.gender) #
print(res.get_gender_display()) # 固定语法记住了 哈 想取得数字所应的是中文的时候 对象.get_字段(gender)_display() 》》》 获取编号对应的中文注释
z注意用户如果想用存的时候
modles.Product.objects.create(...gender=1)伪代码 表示存的时候也是按照数字来存储

 

 

补充图书管理系统:

 

转载于:https://www.cnblogs.com/mofujin/p/11019489.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值