我正在建立一个两名参与者参与比赛的模型。我倾向于这个模型:
def match(models.Model):
player = ForeignKey(Player)
opponent = ForeignKey(Player)
score = PositiveSmallIntegerField()
games_won = PositiveSmallIntegerField()
games_lost = PositiveSmallIntegerField()
won_match = BooleanField()
但是,有统计数据,如果我想完整地描述比赛,则需要另外一次拉动才能找到对手的匹配记录。
或者我可以设置模型以包含完整的统计数据:
def match(models.Model):
home_player = ForeignKey(Player)
away_player = ForeignKey(Player)
home_player_score = PositiveSmallIntegerField()
away_player_score = PositiveSmallIntegerField()
...
但是这看起来同样糟糕,因为我必须为一个玩家做两个逻辑集(当他 home_player 时找到他的分数以及当他 away_player 时他的分数)
最后一个选项是每次匹配两次插入,两次都有完整的统计数据,并在表格中保留冗余数据。
似乎有更好的方法,因此我推测 SO 。
答案 0 :(得分:1)
如果您希望减少冗余并保持逻辑的内容......
匹配度:
- id
- 姓名
Match_Player :(每场比赛2条记录)
- match_id
- player_id
- is_home
Match_Player_Score:
- match_id
- player_id
- 得分
答案 1 :(得分:1)
我选择第一个模型并使用select_related()
来避免额外的数据库调用。
答案 2 :(得分:0)
我会避免在数据库中存在冗余数据。这使得数据库数据内部不一致并且搞乱所有内容的可能性开始存在。
每个匹配使用一个条目,如第二个示例中所示。如果您提前计划,您可以很容易地完成这两组逻辑。看看proxy models。可能有一种优雅的方法 - 让所有逻辑通过get_my_score
和get_opponent_score
等访问器引用数据字段。然后构建一个代理模型类,它可以交换回家。
class match(models.Model):
def get_my_score(self):
return self.home_player_score
def get_opponent_score(self):
return self.away_player_score
def did_i_win(self):
return self.get_my_score() > self.get_opponent_score()
class home_player_match(match):
class Meta:
proxy = True
def get_my_score(self):
return self.away_player_score
def get_opponent_score(self):
return self.home_player_score
或者您可能需要两个代理模型,并且基本模型类中的名称是中性的。这种方法的问题是我不知道如何在不从数据库重新加载的情况下将类从一个代理模型转换为另一个代理模型。你想要像perl一样“失业”。您可以通过使用包含而不是继承来完成此操作。或者可能只是包装类中的一个标志(未存储在数据库中),表示是否要交换字段。但我建议这样的解决方案 - 解决代码中棘手的问题,不要让数据库变得不一致。