【问题标题】:Coalesce must take at least two expressions合并必须至少有两个表达式
【发布时间】:2019-09-22 12:42:30
【问题描述】:

我正在使用 Django 和 Python 3.7。我想写一个 Coalesce 表达式来帮助我写一个更大的 Django 查询。我有

            Coalesce(
                F("votes")
                -
                Subquery(relevant_hour_stats.values('votes_threshold')[:1]),
                output_field=models.FloatField())

这是上下文中的表达式...

qset = (
    ArticleStat.objects
        .all()
        .annotate(
        shifted_article_create_hour=ExtractHour(ExpressionWrapper(
            F('article__created_on')
            +
            timedelta(seconds=avg_fp_time_in_seconds),
            output_field=models.DateTimeField()
        ))
    )
        .annotate(
        votes_above_threshold=(
                Coalesce(
                    F("votes")
                    -
                    Subquery(relevant_hour_stats.values('votes_threshold')[:1]),
                    output_field=models.FloatField())
        ),
    )
        .filter(
        votes_above_threshold__gt=0,
    )
)

但这会导致

Coalesce must take at least two expressions

抱怨这条线

output_field=models.FloatField()

据我所知,我有两种表达方式。该错误还指的是什么?

【问题讨论】:

  • 这两种表达方式是什么?

标签: django python-3.x model coalesce


【解决方案1】:

django 中的“表达式”是django.db.models.expressions.Expression 的实例。

F('votes') — 表达式。

Subquery(...) — 也是表达式。

但是expression+expression == combined_expression 所以F(...) - Subquery(...) 是一个单一的“复杂”表达式。

您需要 Coalesce 的第二个 POSITIONAL 参数:

Coalesce(
    (F(...) - Subquery(relevant_hour_stats.values('votes_threshold')[:1])),  # First expression
    Value(0.0),  # Second expression
    output_field=models.FloatField()
)

而且我认为子查询可能会导致 NULL(不是F()),所以最好只在 Coalesce 中包装子查询:

qset = (
    ArticleStat.objects
        .all()
        .annotate(
            shifted_article_create_hour=ExtractHour(
                ExpressionWrapper(
                    F('article__created_on') + timedelta(seconds=avg_fp_time_in_seconds),
                    output_field=models.DateTimeField()
                )
            ),
        )
        .annotate(
            votes_above_threshold=(  
                # Single expression F()-Coalesce(...) wrapped in parenthesis
                F("votes") - Coalesce(
                    # 2 expressions as arguments to Coalesce:
                    Subquery(relevant_hour_stats.values('votes_threshold')[:1]),
                    Value(0.0),
                    output_field=models.FloatField(),
                )
            ),
        )
        .filter(
            votes_above_threshold__gt=0,
        )
)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-30
    • 2015-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-07
    相关资源
    最近更新 更多