我有一个具有两个字符字段的模型,可以填充其中一个或两个字符字段。我想这样称呼
QuerySet.order_by
:
qs.alias(name=lambda x: if x.field1 then x.field1 else x.field2).order_by('name')
也就是说,对于每一行,如果已定义,则从
field1
中获取排序依据的值;如果未定义,则从 field2
中获取排序依据的值。有没有办法用 Django 查询集来完成这个任务?
Coalsesce
[Django-doc]:
from django.db.models.functions import Coalesce
qs.alias(name=Coalesce('field1', 'field2')).order_by('name')
如果是关于空项目,则需要一个条件表达式 [Django-doc]:
from django.db.models import Case, F, Q, When
qs.alias(
name=Case(
When(Q(field1=None) | Q(field1=''), then=F('field2')),
default=F('field1'),
)
).order_by('name')
是的,这可以通过使用
.annotate()
方法与 django.db.models 中的一些内置工具来实现,请参见下文:
from django.db.models import Case, When, Value, CharField
from django.db.models.functions import Coalesce
qs = YourModel.objects.annotate(
name=Case(
When(field1__isnull=False, then='field1'),
When(field1__isnull=True, then='field2'),
output_field=CharField()
)
).order_by('name')
如果这是您的查询的全部范围,那么更简洁但稍微不透明的方法是:
from django.db.models.functions import Coalesce
qs = YourModel.objects.annotate(
name=Coalesce('field1', 'field2')
).order_by('name')
Coalesce 的工作原理如下(来自文档):
Coalesce
接受至少两个字段名称或表达式的列表,并返回第一个非空值(请注意,空字符串不被视为空值)。每个参数必须具有相似的类型,因此混合文本和数字将导致数据库错误。
我是 .annotate() 的超级粉丝,我认为这是在不使用原始 SQL 的情况下充分利用 Django ORM 的最佳方法之一!