在按字段排序时,似乎Django有点夸张。
我需要对两个查询(queryset
)进行合并,第一个查询被排名,第二个查询则没有,在最终结果中,我想要一个queryset
,因为它将分页。
我将为您提供一个使用User
模型的示例,以便您可以在家中尝试。
from django.contrib.auth.models import User
from django.db.models import F, Value, IntegerField
from django.db.models.expressions import RawSQL
queryset = User.objects
a = queryset.filter(email__contains='a').annotate(rank=RawSQL("rank() OVER (ORDER BY id desc)", [], output_field=IntegerField()))
b = queryset.filter(email__contains='b').annotate(rank=Value(None, output_field=IntegerField()))
a.union(b).order_by(F('rank').desc(nulls_last=True))
# DatabaseError: ORDER BY term does not match any column in the result set.
a.order_by(F('rank').desc(nulls_last=True))
# this is OK
b.order_by(F('rank').desc(nulls_last=True))
# ProgrammingError: non-integer constant in ORDER BY
# LINE 1: ...ERE "auth_user"."email"::text LIKE '%b%' ORDER BY NULL DESC ...
这是Django的错误吗?
我正在使用Django == 1.11.17
答案 0 :(得分:0)
我相信会出现此问题,因为Django仅通过注入Value(None, output_field=IntegerField())
来处理NULL
,而这在ORDER BY
子句中无效。
然后,因为Django将带有注释的表达式作为ORDER BY放置在其中,所以它将使用此值。
我认为解决此问题的唯一方法是让整个查询(即并集的两个部分)在子查询中求值-然后该子查询将具有用于注释的值的列,而不仅仅是表达式自己。
也许您可能会说这是django应该做的,因为它克服了这个问题(并且还意味着该表达式不会在SELECT以及WHERE部分中被数据库多次评估)。