1 环境
Python3.7.3
Django==2.0.6
2. django F()表达式
每次获取times当前的值,再+1,这样需要将times值取出,存到内存中
obj = models.Test.objects.get(name="cox")
obj.times = obj.times + 1
obj.save()
虽然 obj.times = F(“times”) + 1
看起来像常规的Python为实例属性赋值,但实际上它是一个描述数据库上操作的SQL结构
当Django遇到要给F()实例,它会覆盖标准的Python运算符来创建一个封装的SQL表达式;在这个例子中,指示数据库增加由 obj.times 表示的数据库字段。
无论 obj.times 的值是或曾是什么,Python永远不需要知道–完全由数据库来处理。Python通过Django的F()类做的所有事情仅是参考某个字段创建SQL语法来描述操作。
obj = models.Test.objects.get(name="cox")
obj.times = F("times") + 1
obj.save()
因此,F()可以通过以下方式提供性能优势
直接在数据库中操作而不是python
减少一些操作所需的数据库查询次数
#2.2 F()操作在 obj.save() 后会持续存在
如果times的值是1,那么经过n次save()之后,times的值是2
obj = models.Test.objects.get(name="cox")
obj.times = obj.times + 1
obj.save()
obj.save()
obj.save()
如果times的值是1,那么经过n次save()之后,times的值是1+n,而不是2,就是因为F()操作在 obj.save() 后会持续存在
obj = models.Test.objects.get(name="cox")
obj.times = F("times") + 1
obj.save()
obj.save()
obj.save()
#2.3 F()再过滤(filter)中的使用
获取表中收入(input_price)大于支出(output_price)的数据
models.Test.objects.filter(input_price__gt=F("output_price"))
Django支持F()对象使用加、减、乘、除、取模和幂运算等算术操作,两个操作数可以是常数或F()对象
models.Test.objects.filter(input_price__gt=F("output_price")*2)
models.Test.objects.filter(input_price__gt=F("output_price")+F("output_price"))
你还可以在F()对象中使用双下划线标记来跨越关联关系。 带有双下划线的F()对象将引入任何需要的join 操作以访问关联的对象
models.Test.objects.filter(authors__name=F('blog__name'))
对于date 和date/time 字段,你可以给它们加上或减去一个timedelta对象
from datetime import timedelta
models.Test.objects.filter(mod_date__gt=F('pub_date') + timedelta(days=3))
3.Django Q()表达式
当我们在查询的条件中需要组合条件时(例如两个条件“且”或者“或”)时。我们可以使用Q()查询对象
from django.db.models import Q
models.Author.objects.filter(Q(name="cox") | Q(name="Tom")) # 获取在Author表中,name等于cox和name等于cox的所有数据
models.Author.objects.filter(Q(name="cox") & Q(age=12))# 获取在Author表中,name等于cox并且age等于12的所有数据
#2.5 Q()传入条件查询
q1 = Q()
q1.connector = 'OR'
q1.children.append(('name', "cox"))
q1.children.append(('name', "Tom"))
q1.children.append(('name', "Jeck"))
models.Author.objects.filter(q1) # 在Author表中,name等于cox/Tom/Jeck的所有数据
con = Q()
q1 = Q()
q1.connector = 'OR'
q1.children.append(('name', "cox"))
q1.children.append(('name', "Tom"))
q1.children.append(('name', "Jeck"))
q2 = Q()
q2.connector = 'OR'
q2.children.append(('age', 12))
con.add(q1, 'AND')
con.add(q2, 'AND')
models.Author.objects.filter(con) # 在Author表中,name等于cox/Tom/Jeck的 并且 满足age等于12 的所有数据
#2.6 Q()非
在Q()语句中,~代表非
models.Author.objects.filter(~Q(name="cox")) # 获取在Author表中,name不等于cox的所有数据
# 2.7Q 对象可以使用c&(AND)和|(OR)操作符组合起来。
1)当一个操作符在两个Q 对象上使用时,它产生一个新的Q 对象。
例子:
Q(question__startswith='Who') | Q(question__startswith='What')
等同于SQL语句
WHERE question LIKE 'Who%' OR question LIKE 'What%'
2)如果一个查询函数有多个Q 对象参数(逗号隔开的),这些参数的逻辑关系为“AND"。
Poll.objects.get(
Q(question__startswith='Who'),
Q(pub_date=date(2018, 5, 29)) | Q(pub_date=date(2018, 5, 30))
)
#等同于下列SQL语句:
SELECT * from polls WHERE question LIKE 'Who%'
AND (pub_date = '2018-05-29' OR pub_date = '2018-05-30')
3)Q 对象可以使用~ 操作符取反,这允许组合正常的查询和取反(NOT) 查询:
Q(question__startswith='Who') | ~Q(pub_date__year=2017)
4)查询函数可以混合使用Q对象和关键字参数。所有提供给查询函数的参数(关键字参数或Q 对象)都将"AND”在一起。但是,如果出现Q 对象,它必须位于所有关键字参数的前面。例如
Poll.objects.get(
Q(pub_date=date(2018, 5, 29)) | Q(pub_date=date(2018, 5, 30))
question__startswith='Who'
#下列是不合法的查询条件
Poll.objects.get(
question__startswith='Who',
Q(pub_date=date(2005, 5, 2)) | Q(pub_date=date(2005, 5, 6)))