django - Django中的自引用聚合
问题描述
是否可以在 django 中编写自引用聚合?
例如,给定以下模型定义:
from django.db import models
class Match(models.Model):
match_id = models.BigIntegerField(primary_key=True)
start_time = models.DateTimeField()
league = models.ForeignKey(League, on_delete=models.CASCADE)
team = models.ForeignKey(Team, on_delete.models.CASCADE)
我想Match
用先前匹配的数量来注释每个对象。(最终还有其他条件,例如,与给定球队的先前比赛。)
我最初的想法是这样的:
from django.db.models import Q, F, Count
matches = Match.objects.filter(team__name='xyz')
matches.annotate(
prior_matches=Count('match_id', filter=(
Q(start_time__lt=F('start_time')
))
)
不幸的是,这似乎prior_matches=0
适用于所有对象。
这个问题建议遵循外键并使用反向关系,但这似乎很笨拙,而且它也有两个问题:
- 它不是严格等价的。例如,以下代码段有效,但将计算给定联赛中的先前比赛,而不是整体。我想你可以通过创建一个所有对象都作为外键的占位符模型来解决这个问题
Match
,但这似乎并不理想。
matches.annotate(
prior_matches=Sum(Case(
When(start_time__lt=F('league__matches__start_time'), then=1),
default=0,
output_field=models.IntegerField()
))
)
- 提供的计数与数据库中所有先前的匹配相关,而不仅仅是过滤查询集中的匹配。例如,上面的代码查找所有先前匹配的计数,即使查询
matches
集是针对特定团队过滤的。我想不出解决这个问题的好方法(除了在每个Q
/filter
子句中重复应用于查询集的完整过滤条件,这在管理器中是不可推广的)。
作为动机/避免 xy 问题,我希望通过在数据库级别工作来替换的(伪)代码片段之一如下:
def generate_stats(match):
matches = Match.objects.filter(start_time__lt=match.start_time)
for team in (match.home_team, match.away_team):
q_involving = Q(home_team=team) | Q(away_team=team)
team_matches = matches.filter(q_involving)
team_matches.aggregate(...) # get stats
解决方案
我认为您应该将第一个代码更改为
from django.db import models
class Match(models.Model):
match_id = models.AutoField(primary_key=True)
start_time = models.DateTimeField()
league = models.ForeignKey(League, on_delete=models.CASCADE)
team = models.ForeignKey(Team, on_delete.models.CASCADE)
否则,可能是您实际上没有添加“匹配”
推荐阅读
- python-3.x - Model.fit 值误差(文本分类模型)
- python - 在 Tensorflow 2.x 中我们不需要指定输入形状吗?
- wordpress - 如何编写 .htaccess 以将 url 重定向到 AWS CloudFront?
- ios - Swift playground execution aborted
- sql - 使用字母数字和特殊字符值对 varchar 进行排序
- java - 为什么“List myList”作为方法中的参数可以接受 ArrayList
numberList = new ArrayList<>(); - python-3.x - 我想结合 map & lambda 来计算列表中满足给定条件的项目数
- python - 如何在 Open3D 中加载 3D 模型(.obj)?
- python - 将 Spark Data Frame 或 GlobalTempView 与 PySpark 一起使用
- r - 如何使列名中的列成为其值?