自定义模型属性的 Django 交叉关系查询

时间:2021-04-27 10:03:59

标签: mysql django

我希望使用 Django 的 F 来轻松获取交叉关系信息。我之前有一个我想要的工作形式,但我觉得它很丑,所以我过渡到为我的模型制作自定义属性:

    @property
    def stage(self):
        """Returns the competition's stage status by date"""
        now = timezone.now()
        if self.end_date and self.pub_date and self.close_date and self.start_date:
            if self.start_date > now:
                return "Launched"
            elif self.start_date < now < self.end_date:
                return "Commenced"
            elif self.end_date < now < self.close_date:
                return "Scoring"
            else:
                return "Ended"
        return "Inactive"

过去,我使用了一个巨大的 When/Case 块并对此进行了注释。我更喜欢“属性”风格的做事,因为它们的值在聚合时不会混乱。 (例如,当我进行求和等操作时,团队人数会被高估,因此我必须单独进行)

但是,现在我尝试访问时出现错误:(Team->CompetitionTeam->Competition)

F('competitionteam__competition__stage')
  • 有没有办法做到这一点?错误是:(调试并尝试注释上述内容时)
django.core.exceptions.FieldError: Cannot resolve keyword 'stage' into field.
  • 直接从我的代码运行,它不会在注释后立即发出错误,但只有在访问相关 QuerySet 时才会发出错误。
django.core.exceptions.FieldError: Unsupported lookup 'stage' for AutoField or join on the field not permitted, perhaps you meant range?

注意*:如果我不进行注释而是直接从对象访问它们,则没有错误。

1 个答案:

答案 0 :(得分:0)

您不能使用 F 对象访问模型属性,因为当查询访问数据库而数据库无权访问您的 Python 代码时,会使用 F 对象。

我更喜欢使用注释,你说当你有多个注释时,你会因为多计而停止这样做。发生这种情况是因为 Django 的默认注释实现使用连接而不是子查询。 combining multiple aggregations 的文档中对此进行了说明。

我相信这里的解决方案是使用子查询进行注释。 stage 属性不使用任何关系数据,因此您应该可以像以前一样这样做。对于您正在做的其他注释(您提到团队计数和总和),如果不查看模型和要注释的内容,很难准确显示您需要做什么,但是 here are the docs on subquery

您还可以使用包 django-sql-utils,它提供 SubqueryCountSubquerySum 之类的聚合,它们的工作方式与 Django 内置的 CountSum 类似,但已实现使用子查询而不是连接。