开发者

What is the proper model to reduce logic in this situation?

I am setting up a model where two players are involved in a competition. I'm leaning towards this model:

def match(models.Model):
    player = ForeignKey(Player)
    opponent = ForeignKey(Player)
    score = PositiveSmallIntegerField()
    games_won = PositiveSmallIntegerField()
    games_lost = PositiveSmallIntegerField()
    won_match = BooleanField()

There are statistics involved, however, and it would require another pull to find the matching record for the opponent if I want to describe the match in full.

Alternatively I could set up the model to include full stats:

def match(models.Model):
    home_player = ForeignKey(Player)
    away_player = ForeignKey(Player)
    home_player_score = PositiveSmallIntegerField()
    away_player_score = PositiveSmallIntegerField()
    ...

But that seems equally bad, as I would have to do two logic sets for one player (to find his scores when he's ho开发者_如何学JAVAme_player and his scores when he's away_player).

The final option is to do two inserts per match, both with full stats, and keep redundant data in the table.

There seems like a better way, and therefore I poll SO.


Id go with the first model and use select_related() to avoid the extra db calls.


If you're looking to reduce redundancy and maintain consistiency of logic...

Match: - id
- name

Match_Player: (2 records per match)
- match_id
- player_id
- is_home

Match_Player_Score:
- match_id
- player_id
- score


I'd avoid having redundant data in the database. This leaves open the possibility of the database data getting internally inconsistent and messing up everything.

Use a single entry per match, as in your second example. If you plan ahead, you can accomplish the two sets of logic pretty easily. Take a look at proxy models. There might be an elegant way to do this -- have all of your logic refer to the data fields through accessors like get_my_score and get_opponent_score. Then build a Proxy Model class which swaps home and away.

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

Or maybe you want two Proxy models, and have the names in the base model class be neutral. The problem with this approach is that I don't know how to convert a class from one proxy model to another without reloading from the database. You want a "rebless" as in perl. You could do this by using containment rather than inheritance. Or maybe just a flag in the wrapper class (not stored in the database) saying whether or not to swap fields. But I'd recommend some solution like that -- solve the tricky stuff in code and don't let the database get inconsistent.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜