如何解决Django查询“'ExtractHour'对象没有'split'属性”错误?

2024-09-30 22:21:46 发布

您现在位置:Python中文网/ 问答频道 /正文

我使用的是Django和python3.7。我想在较大查询的条件中包含子查询。

from django.db.models.functions import ExtractHour
...
hour_filter = ExtractHour(ExpressionWrapper(
            F("article__created_on") + timedelta(0, avg_fp_time_in_seconds),
            output_field=models.DateTimeField()
        ),
)
query = StatByHour.objects.filter(hour_of_day=OuterRef(hour_filter))

...

包含它的更大的查询是

^{pr2}$

但是,当我运行这个时,我得到了错误

'ExtractHour' object has no attribute 'split'

这意味着什么?我如何调整我的过滤器,使这个错误消失?

编辑:添加生成外部查询的对象的模型。。。

class ArticleStat(models.Model):
    objects = ArticleStatManager()
    article = models.ForeignKey(Article, on_delete=models.CASCADE, related_name='articlestats')
    ...
    votes = models.FloatField(default=0, null=False)

Tags: djangofromimportdbobjectsonmodels错误
3条回答

正如@WillemVanOnsem所指出的:

Use OuterRef when a queryset in a Subquery needs to refer to a field from the outer query. It acts like an F expression except that the check to see if it refers to a valid field isn’t made until the outer queryset is resolved.

然后你做到了:

query = StatByHour.objects.filter(hour_of_day=OuterRef(hour_filter))

其中hour_filter被视为字段查找,Django正在执行一种

^{pr2}$

以收集预期字段查找的部分。在

但是hour_filter在这里是一个ExtractHour,因此出现了错误。在

您可以尝试用所需的小时对文章统计信息进行注释,然后处理结果:

 hour_value = ExtractHour(
    ExpressionWrapper(
        F("article__created_on") + timedelta(0, avg_fp_time_in_seconds),
        output_field=models.DateTimeField()
    ),
)


qset = ArticleStat.objects.annotate(
    hour = hour_value
).filter(
     # ... and write your filter based on the annotate field (hour) here.
)

整个过程可能看起来像(我没有测试过这个,只是为了给你指出正确的方向):

hour_value = ExtractHour(
    ExpressionWrapper(
        F("article__created_on") + timedelta(0, avg_fp_time_in_seconds),
        output_field=models.DateTimeField()
    ),
)


qset = ArticleStat.objects.annotate(
    hour = hour_value
).filter(
    votes__gte=F("article__website__stats__total_score") / 
               F("article__website__stats__num_articles") *
               F("hour") * day_of_week_index
)

附录:

如果仍要在此处使用子查询,可以修改已有的子查询,使其在带注释的字段上工作:

query = StatByHour.objects.filter(hour_of_day=OuterRef('hour'))

祝你好运!在

OuterRef用于从父查询获取一个值,但是这里您根本不需要外部查询的引用。在

from django.db.models.functions import ExtractHour

hour_filter = ExtractHour(
    ExpressionWrapper(
        F('article__created_on') + timedelta(0, avg_fp_time_in_seconds),
        output_field=models.DateTimeField()
    )
)
query = StatByHour.objects.filter(hour_of_day=hour_filter)

所以这里不需要OuterRef。正如documentation on ^{}所说:

Use OuterRef when a queryset in a Subquery needs to refer to a field from the outer query. It acts like an F expression except that the check to see if it refers to a valid field isn’t made until the outer queryset is resolved.

ExtractHour内使用OuterRef


from django.db.models.functions import ExtractHour
...
query = StatByHour.objects.filter(
    hour_of_day=ExtractHour(ExpressionWrapper(
            # NOTE: `OuterRef()+something` works only on Django >= 2.1.0
            OuterRef("article__created_on") + timedelta(0, avg_fp_time_in_seconds),
            output_field=models.DateTimeField()
        ),
    )
)

qset = ArticleStat.objects.filter(
    votes__gte=(
        F("article__website__stats__total_score") 
        / 
        F("article__website__stats__num_articles") 
        *
        Subquery(
            query.values('index')[:1], 
            output_field=FloatField()
        ) 
        *
        day_of_week_index
    ),
)

相关问题 更多 >