按两个字段之一排序

问题描述 投票:0回答:2

我有一个具有两个字符字段的模型,可以填充其中一个或两个字符字段。我想这样称呼

QuerySet.order_by

qs.alias(name=lambda x: if x.field1 then x.field1 else x.field2).order_by('name')

也就是说,对于每一行,如果已定义,则从

field1
中获取排序依据的值;如果未定义,则从
field2
中获取排序依据的值。有没有办法用 Django 查询集来完成这个任务?

django django-queryset
2个回答
0
投票

你要做的基本上是

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')

0
投票

是的,这可以通过使用

.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 的最佳方法之一!

© www.soinside.com 2019 - 2024. All rights reserved.