Django循环模型参考

exf*_*zik 14 python django

我开始在一个小型足球联赛管理网站上工作(主要用于学习目的)并且无法围绕Django模型关系.为简单起见,假设我有两种类型的对象 - 玩家和团队.当然,玩家属于一个团队,因此是玩家模型中的ForeignKey(团队).所以我去:

class Team(models.Model):
    name = models.CharField()
class Player(models.Model):
    name = models.CharField()
    team = models.ForeignKey(Team)
Run Code Online (Sandbox Code Playgroud)

然后我希望每支球队都有一名队长,这将是球员模型中的一名外国球员(球员).但这会产生循环依赖.虽然我的Django体验有限,但它似乎是一个简单的问题,虽然我无法弄清楚我在概念上做错了什么.

sec*_*ond 36

正如您在文档中看到的那样,正是由于这个原因,可以将外部模型指定为字符串.

team = models.ForeignKey('Team')
Run Code Online (Sandbox Code Playgroud)

  • 让我说清楚。现在我有: `class Team(models.Model): name = models.CharField(max_length=50, unique=True) Captain = models.ForeignKey('Player', related_name='captain') class Player(models.Model) : name = models.CharField(max_length=50) team = models.ForeignKey(Team)` 但这会生成不同的 SQL 表。“team”表具有“captain_id”整数NOT NULL,而“player”表具有“team_id”整数NOT NULL REFERENCES“tm_team”(“id”)`,因此似乎将外部模型指定为字符串会产生不同的结果。 (2认同)
  • @middus 嗯,我不知道这种事情是如何完成的,这就是我问的原因。如果唯一的方法是使用这样的解决方法,那么我会采取它。然而,我原以为会有一种不是解决方法的方法。 (2认同)

exf*_*zik 9

这是解决这个问题的另一种方法.我创建了一个存储玩家和团队之间关系的附加表,而不是创建循环依赖.所以最后它看起来像这样:

class Team(Model):
    name = CharField(max_length=50)

    def get_captain(self):
        return PlayerRole.objects.get(team=self).player

class Player(Model):
    first_name = CharField(max_length=50)
    last_name = CharField(max_length=50, blank=True)

    def get_team(self):
        return PlayerRole.objects.get(player=self).team

PLAYER_ROLES = (
    ("Regular", "Regular"),
    ("Captain", "Captain")
    )

class PlayerRole(Model):
    player = OneToOneField(Player, primary_key=True)
    team = ForeignKey(Team, null=True)
    role = CharField(max_length=20, choices=PLAYER_ROLES, default=PLAYER_ROLES[0][0])
    class Meta:
        unique_together = ("player", "team")
Run Code Online (Sandbox Code Playgroud)

它的存储效率可能略低于建议的解决方法,但它避免了循环依赖性并保持数据库结构清晰.欢迎评论.


Mic*_*ick 7

您可以在尚未定义的模型的外键中使用完整的应用程序标签,并使用related_name来避免名称冲突:

class Team(models.Model):
    captain = models.ForeignKey('myapp.Player', related_name="team_captain")

class Player(models.Model):
    team = models.ForeignKey(Team)
Run Code Online (Sandbox Code Playgroud)


mim*_*lea 5

这就是您正在寻找的:

class Team(models.Model):
    name = models.CharField()
    captain = models.ForeignKey('Player')
class Player(models.Model):
    name = models.CharField()
    team = models.ForeignKey(Team)
Run Code Online (Sandbox Code Playgroud)