在django中过滤带注释的列
Filter on annotated column in django
我有两个模型:
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。它排除了同时存在两个 StateChanges 的项目,当我查看生成的查询时,我明白了为什么它会这样做。
如果我不排除任何东西,它会为每个案例显示 1 行。
任何人都可以给我一些关于如何让 django 创建我需要的 JOIN 的提示吗?
我们使用 .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"
})
我有两个模型:
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。它排除了同时存在两个 StateChanges 的项目,当我查看生成的查询时,我明白了为什么它会这样做。
如果我不排除任何东西,它会为每个案例显示 1 行。
任何人都可以给我一些关于如何让 django 创建我需要的 JOIN 的提示吗?
我们使用 .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"
})