在本教程中,我们将学习查询表达式、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)            # <CombinedExpression: F(price) + Value(1)>
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是IntergerField,我们需要将表达式包装在ExpressionWrapper对象中。

F() 表达式也可用于过滤数据。

Student.objects.filter(fees__gte=F(2000))

F() 表达式可以提供以下优势:

  • 帮助我们通过数据库获取数据,并限制Python访问数据库的方式。
  • 帮助减少特定操作的查询次数。

使用F() 避免竞态条件。

F() 表达式还提供其他功能,例如更新字段的值可以避免竞态条件。

让我们更好地理解它——如果两个Python线程执行该代码,其中一个线程在另一个线程从数据库中检索数据之后,检索、增加并保存字段的值。该线程保存的值将基于原始值。第一个线程的过程将被使用。

每次涉及更新字段的数据库操作,该过程都会变得更加稳健。F() 表达式将根据在执行save()或update()时数据库中字段的值来更新该字段。

使用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() 中,允许在更复杂的表达式中使用简单的值。

value参数会自动将值包含在表达式中,这些值可以是1、True或None。Django会将这些Python值转换为相应的数据库类型。output_field参数必须是模型字段实例,例如IntegerField()或BooleanField()。

标签: django语言, django教程, django技术, django学习, django学习教程, django下载, django开发, django入门教程, django进阶教程, django高级教程, django面试题, django笔试题, django编程思想