Django:从查询集中删除辅助注解

uurity8g  于 2023-10-21  发布在  Go
关注(0)|答案(3)|浏览(117)

我正在一个复杂的数据模型上建立一个复杂的查询集。查询集必须返回带有注解ann的模型对象A的选择。
为了计算ann,我需要一个辅助注解aux,但是在查询集的最终结果中不允许存在aux

qs = A.objects.filter(...)  # complicated
qs = qs.annotate(aux=...)  # complicated
qs = qs.annotate(ann=Case(
    When(condition=Q(aux=0), 
         then Value('some')),
    When(condition=Q(aux_gt=0),
         then Value('other'))))

如何返回带有ann但不带auxqs
(或者:如果aux是一个计数,而ann区分零和非零aux,那么是否有更好的方法来解决整个问题?)

cgyqldqp

cgyqldqp1#

Django 3.2引入了一个功能来专门解决这个问题:
https://docs.djangoproject.com/en/3.2/ref/models/querysets/#alias
alias()的工作方式类似于annotate(),除了其他查询集方法,如annotate():它不会停留在最终输出中。

qs = A.objects.filter(...)
qs = qs.alias(aux=...)  # using alias here instead of annotate
qs = qs.annotate(ann=Case(
When(condition=Q(aux=0), 
     then Value('some')),
When(condition=Q(aux_gt=0),
     then Value('other'))))
wr98u20j

wr98u20j2#

丑陋的黑客:

一个简单的方法是将aux也重命名为ann。这样,第二个注解将覆盖第一个注解,第一个注解将不再存在于输出中。

qs = A.objects.filter(...)  # complicated
qs = qs.annotate(ann=...)  # complicated
qs = qs.annotate(ann=Case(
    When(condition=Q(ann=0), 
         then Value('some')),
    When(condition=Q(ann_gt=0),
         then Value('other'))))

这似乎起作用了。在SQlite和PostgreSQL上使用Django 1.11进行测试。
但一定有更好的办法,拜托。

lymgl2op

lymgl2op3#

它没有文档记录,但有一个QuerySet().query.annotations字典,您可以操作它来从结果中删除注解:

qs = A.objects.filter(...)  # complicated
qs = qs.annotate(aux=...)  # complicated
qs = qs.annotate(ann=Case(
    When(condition=Q(aux=0), 
         then Value('some')),
    When(condition=Q(aux_gt=0),
         then Value('other'))))

qs.query.annotations.pop('aux')

它既适用于您提到的“辅助注解”,也适用于过滤。例如,如果你只是想过滤它们,你可以在最后删除所有的注解:

qs = A.objects.filter(...)  # complicated
qs = qs.annotate(aux=...)  # complicated
qs = qs.annotate(ann=Case(
    When(condition=Q(aux=0), 
         then Value('some')),
    When(condition=Q(aux_gt=0),
         then Value('other'))))
qs = qs.filter(ann='some')
qs.query.annotations.pop('aux', None).pop('ann', None)

但是如果你能负担得起使用较新的django(3.2+),那么就像另一个答案中建议的那样使用qs.alias()https://stackoverflow.com/a/69486332/952437

相关问题