[英]How to properly use order_by with nulls_last on a related one_to_many field?
I'm trying to filter and order objects by existance of a related model with forcing nulls as last.我正在尝试通过相关 model 的存在来过滤和排序对象,最后强制为空。
Example models:示例模型:
class ModelA(models.Model):
name = models.CharField(max_length=255)
...
class ModelB(models.Model):
model_a = models.ForeignKey(ModelA, related_name=model_b)
date = models.DateField()
time = models.TimeField()
...
Now, I need to filter ModelA by some kwargs (normal operations), but I also need to order ModelA by nearest ModelB date and time (in future, not past) ascending or descending WITH A SINGLE QUERY PARAM and also NULLS need to be placed last regardless of ascending or descending order.现在,我需要通过一些 kwargs(正常操作)过滤 ModelA,但我还需要通过最近的 ModelB 日期和时间(将来,而不是过去)对 ModelA 进行排序,使用单个查询参数升序或降序,还需要放置 NULL最后不管升序还是降序。
I already came to a conclusion that I need to overwrite default QuerySet order_by:我已经得出结论,我需要覆盖默认的 QuerySet order_by:
class ModelAQuerySet(models.QuerySet):
def order_by(self, *field_names):
if 'model_a_date' in field_names or '-model_a_date' in field_names:
field_names = list(field_names)
if 'model_a_date' in field_names:
field_names.remove('model_a_date')
return super().order_by(
'model_b__date',
'model_b_time',
*field_names
)
else:
field_names.remove('-model_a_date')
return super().order_by(
'-model_b__date',
'-model_b__time',
*field_names
)
else:
return super().order_by(*field_names)
It works fine when I'm ordering descending ( '-model_a_date'
), since NULLS are last, but I'm having a hard time placing nulls last in ascending order.当我按降序(
'-model_a_date'
)排序时它工作正常,因为 NULLS 是最后一个,但我很难将空值按升序排列在最后。 I already tried:我已经尝试过:
return super().order_by(
F('model_b').asc(nulls_last=True),
'model_b__date',
'model_b__time',
*field_names
)
####
return super().order_by(
F('model_b').asc(nulls_last=True)
).order_by(
'model_b__date',
'model_b_time',
*field_names
)
####
return super().order_by(
'model_b__date',
'model_b_time',
*field_names
).order_by(
F('model_b').asc(nulls_last=True),
)
but that does not work at all.但这根本行不通。 Either when I put inside order_by along with other arguments, or as a separate order_by in front or after the above order_by.
当我将 order_by 与其他 arguments 一起放入 order_by 时,或者作为单独的 order_by 在上述 order_by 之前或之后。
Any ideas on that?对此有什么想法吗? Has anyone bumped into such problem?
有没有人遇到过这样的问题? I'm in a pickle here and honestly I ran out of ideas.
我在这里陷入困境,老实说,我已经没有想法了。 Thanks in advance.
提前致谢。
EDIT编辑
I also tried.union like so:我也试过.union 像这样:
ModelA.objects.annotate(
modelbs=Count('modelb')
).filter(
modelbs__gt=0
).union(
ModelA.objects.annotate(
modelbs=Count('model_b')
).filter(
modelbs=0
)
)
But this comes out with an error:但这会出现错误:
ORDER BY term does not match any column in the result set.
If you use chain you can:如果你使用链,你可以:
Does that make sense?那有意义吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.