我将 Django 查询集基于一个功能正常的 postgres 查询,该查询具有以下 WHERE 条件:
... WHERE COALESCE("project_story"."owner_id" = [INSERT_USER_ID], "project_story"."published_date" IS NOT NULL)
英文:如果用户是故事的所有者,则包含该故事。如果用户不是所有者并且故事未发布,则将其排除。
理想情况下,Django ORM 应该允许类似以下内容:
queryset = queryset.filter(
Coalesce(
Q(owner_id=user.id),
Q(published_date__isnull=False)
)
)
但是在执行时,Django 抛出错误:
TypeError: 'Coalesce' object is not iterable
不幸的是,我需要在数据库级别进行条件过滤。
是否有允许使用合并表达式进行选择的符号或方法?
我不想使用 rawsql 或 queryset.extra。
最佳答案
这是我自己想出来的。由于尚未发布真正的答案,这是我的解决方案:
return queryset.all().annotate(
viewable=Case(
When(owner_id=user.id, then=True),
When(published_date__isnull=False, then=True),
default=False,
output_field=db.models.BooleanField()
),
).filter(
viewable=True
)
很难读,不是吗?生成的 SQL 也同样丑陋:
AND CASE WHEN ("project_story"."owner_id" = [INSERT USER ID]) THEN True WHEN ("project_story"."published_date" IS NOT NULL) THEN True ELSE False END = True) ORDER BY "project_story"."image_count" DESC
尽管使用 CASE 会得到与原始查询相同的结果,但我仍然希望代码更简洁。
在那之前,我会将我的问题标记为已回答。
关于python - 如何仅使用 CASE 或 COALESCE 表达式来过滤 Django 查询集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48270038/