您的位置:首页 > Web前端

django模型层FQ查询,only,defer关键字,orm简单事务

2019-06-13 20:57 671 查看

前言:
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)
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: