搜索表达式的文档页面以查看许多示例:https ://docs.djangoproject.com/en/3.2/ref/models/expressions/
output_field
如果 Django 没有足够的启发式方法来自行确定,则该参数用于解决表达式中的冲突或模棱两可的类型。
- Django
output_field
为你提供了一个路由来告诉它你真正想要的输出类型。
- 该
output_field
参数不是为了让您转换值的类型,而是帮助 Django 在竞争选项中解析输出类型。
- 该
output_field
参数并不总是必需的,但有时它会解决歧义,否则会导致 Django 引发异常。
看看你的例子,我只能假设 Djangooutput_field
在这些情况下无视你。
关于两者输出的不同,Django 将裸字符串"id"
视为字段名。如果您像“yes”一样使用字符串包裹"id"
字符串,您会看到返回的是。如果您从示例中删除了包装器,您会看到:Value("id")
"id"
Value
"yes"
FieldError: Cannot resolve keyword 'yes' into field. Choices are: ...
作为一个更复杂的示例来说明output_field
参数如何有用,请考虑 MS SQL Server,它没有适当的布尔类型,而是使用位字段来代替。
尝试
queryset = queryset.annotate( foo=Case(When(name__icontains='XYZ', then=Value(True)), default=Value(False)) )
给出
django.core.exceptions.FieldError: Cannot resolve expression type, unknown output_field
即使您已经提交了两个明确的布尔值,Django 也找不到要返回的正确类型。
这就是output_field
它的用途。您可以通过提供要使用的类型来解决 Django 的歧义:
queryset = queryset.annotate( foo=Case(When(name__icontains='XYZ', then=Value(True)), default=Value(False), output_field=BooleanField()) )
显然 Django 很乐意尝试,但无法在 MS SQL Server 下完成:
django.db.utils.ProgrammingError: ('42000', '[42000] [FreeTDS][SQL Server]Statement(s) could not be prepared. (8180) (SQLExecDirectW)')
因此,要真正帮助 Django,您需要比 Django 了解更多 [原文如此] 并提供:(有效
queryset = queryset.annotate( foo=Case(When(name__icontains='XYZ', then=Value(True)), default=Value(False), output_field=BinaryField()) )
)。
将此应用于您的示例:MyModel.objects.annotate(foo=Max(False, output_field=BooleanField())).first().foo
返回False
。
即使使用数值,Django 也能够根据您提供的output_field
:MyModel.objects.annotate(foo=Max(0, output_field=BooleanField())).first().foo
返回值来解释该值False
。
但正如我们所见,虽然 Django 可以处理这个问题,但 MS SQL Server 不会容忍布尔值,因为它没有布尔值;所以你可能会发现你需要在 MS SQL Server 的特定情况下执行此操作:MyModel.objects.annotate(foo=Max(0, output_field=BinaryField())).first().foo
返回0
.
因此,该output_field
参数提供了这种额外的控制。