Python技术迷

Django教程-如何使用 F() 表达式

整理:python架构师
在本教程中,我们将学习查询表达式、F 表达式以及如何在 QuerySet 中使用它。让我们对查询表达式进行简要介绍。

什么是查询表达式?

查询表达式表示可以作为更新、创建、过滤、排序、注释或聚合的一部分的值或计算。如果表达式以布尔值返回输出,则可以直接用于过滤器中。Django 提供了许多内置表达式,帮助我们编写查询。查询表达式可以嵌套或组合。

F() 表达式

F() 对象指定了模型字段的值,或者直接引用数据库中的模型字段值。让我们来看一个简单的例子,一个名为Student的类有一个fees字段,我们想要增加学生20%的费用。
可以使用如下代码完成:
student = Student.objects.all()for stu in student:    stu.fees *= 1.2

专属福利 

👉点击领取:最全Python资料合集

我们可以使用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.2student.save()
但是要小心使用这种赋值方式,F() 对象在保存模型后会保留。
student.fees                   # fees = Decimal('10.00')student.fees = F('fees') + 1student.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') + 1product.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 FStudent.objects.order_by(F('fees_paid').desc(nulls_last=True))

Func() 表达式

Func() 表达式涉及数据库函数,例如COALESCE和LOWER,或者聚合函数如SUM。我们可以直接使用它们。
例如:
from django.db.models import F, Funcqueryset.annotate(field_lower=Func(F('field'), function='LOWER'))

聚合表达式

聚合表达式是Func() 表达式的重要组成部分。它通知查询需要GROUP BY子句。所有聚合函数都继承自Aggregate()。
例如:
from django.db.models import CountStudent.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()。
Image
 1
Image
热门推荐

Image