Django 如何使用F()表达式
在本教程中,我们将学习关于查询表达式、F表达式以及如何在QuerySet中使用它。让我们简要介绍一下查询表达式。
什么是查询表达式
查询表达式表示可以作为更新、创建、过滤、排序、注释或聚合的一部分的值或计算。如果表达式返回的是布尔值,它可以直接用于过滤。Django提供了许多内置的表达式,帮助我们编写查询。查询表达式可以嵌套或组合使用。
类F()表达式
F()对象指定了模型字段的值,或者它直接引用数据库中的模型字段值。让我们举一个简单的示例,有一个名为 Student 的班级,其中有一个字段叫做fees,我们想要增加学生的费用20%。
可以按如下方式实现。
student = Student.objects.all()
for stu in student:
stu.fees *= 1.2
我们可以使用F()表达式在单个查询中完成这个操作。
from django.db.models import F
Student.objects.update(fees=F('fees') * 1.2)
我们还可以使用以下方法。
student = Student.objects.get(pk=1)
student.price = F('fees') * 1.2
student.save()
不过要小心处理这种任务。F()对象在保存模型后会持久存在。
student.fees # fees = Decimal('10.00')
student.fees = F('fees') + 1
student.save() # fees = Decimal('11.00')
student.name = 'What the F()'
student.save() # fees = Decimal('12.00')
在字段更新后,该特定字段将包含一个实例: django.db.models.expression.CombinedExpression ,而不是实际结果。我们可以立即访问结果,如下所示。
student.fees= F('fees') + 1
product.save()
print(student.fees) #
product.refresh_from_db()
print(student.fees)
我们还可以使用数据的注释。
from django.db.models import ExpressionWrapper, DecimalField
Product.objects.all().annotate(
value_in_stock=ExpressionWrapper(
F('fees') * F('rollno'), output_field=DecimalField()
)
)
由于 fees 是一个 DecimalField ,而 rollno 是一个 IntegerField ,我们需要将表达式包装在一个 ExpressionWrapper 对象中。
它也可以用来过滤数据。
Student.objects.filter(fees__gte=F(2000))
F()表达式可以提供以下几个优势。
- 它可以帮助我们获得数据库,并限制Python访问数据库。
- 它可以帮助减少特定操作的查询次数。
使用F()避免竞态条件
F() 表达式还提供了其他功能,如更新字段值来避免竞态条件。
让我们以更好的方式理解 – 如果两个Python线程执行该代码,则一个线程可以在另一个线程从数据库中检索该代码之后检索、递增和保存该代码。线程保存的值将基于原始值。第一个线程的过程将被使用。
每次涉及更新字段时,该过程将变得更加强大。当执行 save() 或 update() 时, F() 表达式将根据数据库中字段的值来更新字段。
使用F()来排序空值
我们可以使用 F() 和 nulls_first 或 nulls_last 关键字参数来控制字段空值的排序顺序。
让我们看下面的示例,对在新学期后未交费的学生进行排序。
from django.db.models import F
Student.objects.order_by(F('fees_paid').desc(nulls_last=True))
Func()表达式
Func()表达式涉及数据库函数,例如COALESCE和LOWER,或者聚合函数如SUM。我们可以直接使用它们。
示例 –
from django.db.models import F, Func
queryset.annotate(field_lower=Func(F('field'), function='LOWER'))
聚合表达式
聚合表达式是 Func() 表达式的重要组成部分。它告知查询需要 GROUP BY 子句。所有的聚合函数都继承自 Aggregate() 。
示例 –
from django.db.models import Count
Student.objects.annotate(
managers_required=(Count('num_employees') /8 ) + Count('num_managers'))
Value() 表达式
Value() 对象代表表达式的最小组成部分。我们可以使用 Value() 来表示表达式内的整数、布尔或字符串值。
Value() 表达式很少直接使用。当我们编写表达式 F(‘field’) + 1 时,Django 会隐式地将1包装在 Value() 中,允许在更复杂的表达式中使用简单值。
值参数自动包含在表达式中,这些值可以是1、True或None。Django 将这些Python值转换为相应的数据库类型。而 output_field 参数必须是模型字段实例,例如 IntegerField() 或 BooleanField() 。