【问题标题】:What is the proper model to reduce logic in this situation?在这种情况下减少逻辑的正确模型是什么?
【发布时间】:2011-02-26 06:33:53
【问题描述】:

我正在建立一个模型,其中两名玩家参与比赛。我倾向于这种模式:

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

【问题讨论】:

    标签: python sql django schema


    【解决方案1】:

    我选择第一个模型并使用select_related() 以避免额外的数据库调用。

    【讨论】:

      【解决方案2】:

      如果您希望减少冗余并保持逻辑一致性...

      比赛: - 身份证
      - 名称

      Match_Player:(每场比赛 2 条记录)
      - match_id
      - player_id
      - is_home

      Match_Player_Score:
      - match_id
      - player_id
      - 得分

      【讨论】:

      • 达到您满意的模型的典型方法是尽可能地标准化所有内容。编写你的逻辑,然后在必要时完成优化/去规范化(无论是执行时间、使用的空间、可维护性等),但只有在你弄清楚其他所有事情后才这样做。
      • 所以,是的,很可能最后两个表可以合并。但是,当您仍在改进设计时,单独的表格可以为意外(或客户的新要求)提供更大的灵活性
      【解决方案3】:

      我会避免在数据库中有冗余数据。这留下了数据库数据内部不一致并搞砸一切的可能性。

      每场比赛使用一个条目,如第二个示例所示。如果你提前计划,你可以很容易地完成这两组逻辑。看看proxy models。可能有一种优雅的方法来做到这一点——让你的所有逻辑都通过get_my_scoreget_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 中的“rebless”。您可以通过使用包含而不是继承来做到这一点。或者可能只是包装类中的一个标志(未存储在数据库中),表示是否交换字段。但我会推荐一些这样的解决方案——解决代码中的棘手问题,不要让数据库变得不一致。

      【讨论】:

        猜你喜欢
        • 2014-05-14
        • 1970-01-01
        • 2018-05-03
        • 1970-01-01
        • 2013-04-23
        • 1970-01-01
        • 2011-03-26
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多