过滤django中带注释的列

时间:2016-01-22 09:47:55

标签: python django django-models django-orm

我有两种模式:

class Project(models.Model):
    ...

class StateChange(models.Model):
    created_at = models.DateTimeField(default=now, db_index=True)
    project = models.ForeignKey("project.Project")
    state = models.IntegerField(choices=PROJECT_STATE_TYPES, db_index=True)
    ...

模型是链接的,我需要一个项目列表,如果有的话,将由相关的StateChange过滤。 我像这样构建我的查询集:

state_checked = Case(
    When(statechange__state=PROJECT_STATE_CHECKED, then=F('statechange__created_at'))
)
state_construction_ordered = Case(
    When(statechange__state=PROJECT_STATE_CONSTRUCTION_ORDERED, then=F('statechange__created_at'))
)
qs = Projekt.objects.visible_for_me(self.request.user) \
    .annotate(date_reached_state_checked=state_checked) \
    .annotate(date_reached_state_construction_ordered=state_construction_ordered)\
    .exclude(Q(date_reached_state_checked__isnull=True) & Q(statechange__state=PROJECT_STATE_CHECKED) |
             Q(date_reached_state_construction_ordered__isnull=True) & Q(statechange__state=PROJECT_STATE_CONSTRUCTION_ORDERED))

项目可能没有匹配的StateChange,或者一个或两个。

我需要列表在所有情况下显示一个项目行。我的查询集仅适用于零个或一个匹配的StateChange。它排除了两个StateChange都存在的项目,并且当我查看生成的查询时,我知道它为什么会这样做。

如果我不排除任何内容,则每个案例显示1行。

任何人都可以给我一个关于如何让django创建我需要的JOIN的提示吗?

1 个答案:

答案 0 :(得分:0)

我们是通过使用.extra():

来完成的
return Projekt.objects.all().extra(
    select={
        "date_reached_state_checked": "SELECT created_at FROM tracking_statechange WHERE tracking_statechange.projekt_id = projekt_projekt.id AND tracking_statechange.state = 20",
        "date_reached_state_construction_ordered": "SELECT created_at FROM tracking_statechange WHERE tracking_statechange.projekt_id = projekt_projekt.id AND tracking_statewechsel.state = 50"
    })