Django - 异构查询

时间:2014-06-03 15:17:25

标签: django inheritance orm

考虑这个模型:

SoccerMatch(Model):
    """
    FIFA World Cup 2014 match. It could have no teams yet
    if it's scheduled but a shootout stage (they are never
    defined until both previous winner are determined)
    """
    #this is defined beforehand
    date = DateTimeField()
    #this is defined beforehand -for group matches- and when
    #the previous winners are determined -for shootout matches-
    team1 = ForeignKey(Team, related_name="+", null=True)
    team2 = ForeignKey(Team, related_name="+", null=True)
    #these are defined when the match ends
    goals1 = PositiveSmallIntegerField(null=True, blank=True)
    goals2 = PositiveSmallIntegerField(null=True, blank=True)

GroupSoccerMatch(SoccerMatch):
    """
    FIFA World Cup 2014 match for first stage.
    Each group has 4 teams and plays 6 matches.
    """
    group = ForeignKey(Group, related_name="matches")

ShootoutSoccerMatch(SoccerMatch):
    """
    FIFA World Cup 2014 match for second stage.
    Second stage plays 16 matches in rounds of
    8, 4, 2, 1 (3rd and 4th) and 1 (1st and 2nd).
    """

    #... more fields related to the shootout hierarchy
    #....those fields are omitted since they don't matter here

    #this is defined when the match ends
    penalty_shootout = PositiveSmallIntegerField(null=True, blank=True, choices=((1, "Team 1 won"), (2, "Team 2 won")))

在这段代码中(我省略了团队和团队定义,因为它涉及到有关数据和关于问题的微不足道的琐事)我模拟足球比赛世界杯(目前只适用于这个世界杯)和我想要对匹配结果做出预测。

考虑以前的模型有自己的clean()方法。

此应用程序可以配置为具有准确的预测(您必须猜测两个团队的目标和惩罚轮次 IF EXISTS 的获胜者)或不准确的预测(您必须猜测目标中的赢家数量)或者,如果他们绑定了和PENALTY ROUND EXISTS ,则该罚款轮次的获胜者。)

在这两种情况下,我都要考虑罚球,这是不可能的(前48场比赛,根本不存在)。

我的预测模型类是:

class Prediction(Model)
    user = ForeignKey(User, related_name="predictions")
    match = ForeignKey(SoccerMatch, related_name="predictions")
    goals1 = PositiveSmallIntegerField(null=True, blank=True)
    goals2 = PositiveSmallIntegerField(null=True, blank=True)
    penalty_shootout = PositiveSmallIntegerField(null=True, blank=True, choices=((1, "Team 1 won"), (2, "Team 2 won")))

考虑最简单的情况:精确预测 - 一个好的预测有目标1 = match.goals1,goals2 = match.goals2,penalty_shootout = match.penalty_shootout。

我以为我可以解决这样的准确预测:

#1 we consider predictions from a specific user
done_predictions = Prediction.objects.filter(user=anUser)

#2 we consider resolved predictions (i.e. involving matches played)
resolved_predictions = done_predictions.filter(match__date__lt=now() + timedelta(hours=1, minutes=30), match__goals1__isnull=False, match__goals2__isnull=False)

#3 we consider accurate predictions
accurate_predictions = resolved_predictions.filter(goals2=F('match__goals2'), goals1=F('match__goals1'))

现在一切都很好,但我有一个问题:我想考虑最近16场比赛的情况,其中我必须计算点球大战阶段的机会

:有没有办法可以修复第二个和第三个查询来考虑这种情况而不是(制作两个)单独的查询? (这意味着:无法查询match__penalty_shootout=,因为SoccerMatch不是那个字段)或者:有没有办法声明一个"虚构字段" penalty_shootout匹配的组的虚拟值为None?

1 个答案:

答案 0 :(得分:0)

该死的。找到了解决方法。

Django允许通过查询参数查找遍历派生属性(例如管理器,以及django 1.7中的自定义变换)。

对于我的问题,我的逻辑可以确定是否定义了penalty_shootout(1或2是绑定时射击匹配的唯一允许值)或者是无。

如果匹配不是Shootout而是组匹配,则该匹配记录将不存在Shootout片段。因此,当查询match__shootoutsoccermatch__penalty_shootout时,如果未指定值(即没有平局)或者当Shootout子类记录不存在时,我将得到None。因此,对于我的示例,查询match__shootoutsoccermatch__penalty_shootout__isnull=Truematch__goals1=F('match__goals2')我指定了tie,并且由于clean()实现,None不能表示任何内容,但匹配不是Shootout。