簡體   English   中英

如何僅使用 CASE 或 COALESCE 表達式過濾 Django 查詢集?

[英]How can I filter a Django queryset using just a CASE or a COALESCE expression?

我將 Django 查詢集基於具有以下 WHERE 條件的功能性 postgres 查詢:

... 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”對象不可迭代

不幸的是,我需要在數據庫級別進行條件過濾。

是否有允許使用 Coalesce 表達式進行選擇的符號或方法?

我不想使用 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 會導致與原始查詢相同的結果,但我仍然希望使用不那么冗長的代碼。

在那之前,我會將我的問題標記為已回答。

用於為 COALESCE() 編寫自己的 Expression 類的代碼片段的微小開頭,請參閱下面的官方文檔鏈接以獲取完整源代碼。

注意:並非所有數據庫都有 COALESCE(),我認為這就是為什么這不是官方表達式的原因。 可能可以編寫一些代碼將其轉換為標准 Case(...) 表達式作為后備,然后使用 COALESCE() 進行特定於 db 的 sql 轉換。 我把它作為練習留給讀者;-)

from django.db.models import Expression

class Coalesce(Expression):
    template = 'COALESCE( %(expressions)s )'

    ...

完整代碼的官方文檔: Django Models - Writing your own Query Expressions

我相信 Q() 的結果總是 True 或 False,所以在 Coalesce 表達式中使用它是行不通的。 解決方案是使用條件表達式,結合 Case 和 filter。 您可以在文檔中找到所需所有信息。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM