Подтвердить что ты не робот

Ссылка на круговую диаграмму Django

Я начинаю работать на небольшом веб-сайте управления футбольной лигой (в основном в учебных целях) и не могу обдумать отношения модели Django. Для простоты предположим, что у меня есть 2 типа объектов - Player и Team. Естественно, что игрок принадлежит одной команде, так что ForeignKey (Team) в модели Player. Поэтому я иду:

class Team(models.Model):
    name = models.CharField()
class Player(models.Model):
    name = models.CharField()
    team = models.ForeignKey(Team)

Затем я хочу, чтобы у каждой команды был капитан, который был бы одним из игроков, так что это был бы ForeignKey (Player) в модели Team. Но это создаст циклическую зависимость. Конечно, мой опыт Django ограничен, но это кажется простой проблемой, хотя я не могу понять, что я делаю неправильно концептуально.

4b9b3361

Ответ 1

Вот еще один способ решить эту проблему. Вместо создания циклической зависимости я создал дополнительную таблицу, в которой хранятся отношения между игроками и командами. Поэтому в конце он выглядит следующим образом:

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")

Он может быть немного менее эффективным с точки зрения хранения, чем предлагаемый метод обхода, но он избегает циклической зависимости и сохраняет структуру БД чистой и понятной. Комментарии приветствуются.

Ответ 2

как вы можете видеть в docs, именно по этой причине можно указать внешнюю модель в виде строки.

team = models.ForeignKey('Team')

Ответ 3

Вы можете использовать полную метку приложения во внешнем ключе для модели, которая еще не определена, и использовать связанное имя, чтобы избежать конфликта имен:

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

class Player(models.Model):
    team = models.ForeignKey(Team)

Ответ 4

Это то, что вы искали:

class Team(models.Model):
    name = models.CharField()
    captain = models.ForeignKey('Player')
class Player(models.Model):
    name = models.CharField()
    team = models.ForeignKey(Team)

Ответ 5

У вас есть таблица капитана, в которой есть столбики игрока/команды вместе с вашими другими таблицами, и сделайте капитан методом команды:

class Team(models.Model):
    name = models.CharField()
    def captain(self):
      [search Captain table]
      return thePlayer

class Player(models.Model):
    name = models.CharField()
    team = models.ForeignKey(Team)

class Captain(models.Model):
    player = models.ForeignKey(Player)
    team = models.ForeignKey(Team)

Вам нужно будет проверить, что у вас никогда не было более одного капитана в одной команде, хотя... Но у вас нет круговых ссылок. Вы также можете оказаться в капитане, которого нет в команде, которую он назвал капитаном. Таким образом, есть несколько ошибок.

Ответ 6

Хотя нет ничего плохого в том, что у вас есть две ссылки на одну и ту же модель, возможно, есть лучший способ решить эту конкретную проблему.

Добавьте логическую модель Team для определения комбинации игрока + команды в качестве капитана:

class Team(models.Model):
  player = models.ForeignKey(Player)
  name = models.CharField(max_length=50)
  is_captain = models.BooleanField(default=False)

Чтобы найти капитана команды:

Team.objects.filter(is_captain=True)

Лично мне не нравится этот метод, потому что семантика поиска не имеет смысла (т.е. "команда" не является "капитаном" ).

Другой подход заключается в определении позиции каждого игрока:

class Player(models.Model):
   name = models.CharField(max_length=50)
   position = models.IntegerField(choices=((1,'Captain'),(2,'Goal Keeper'))
   jersey = models.IntegerField()

   def is_captain(self):
     return self.position == 1

class Team(models.Model):
   name = models.CharField(max_length=50)
   player = models.ForeignKey(Player)

   def get_captain(self):
      return self.player if self.player.position == 1 else None

Это немного более полезно при поиске:

Player.objects.filter(position=1) (вернуть всех капитанов)

Team.objects.get(pk=1).get_captain() (верните капитана для этой команды)

В любом случае, однако, вы должны выполнить некоторые предварительные проверки, чтобы убедиться, что для определенной позиции есть только один игрок.

Ответ 7

Ни один из ответов здесь не очень хорош - создание круговых ссылок никогда не является хорошей идеей. Представьте себе, если ваша база данных разбилась, и вам пришлось создавать ее с нуля - как вы создадите игрока до создания команды, и наоборот? Посмотрите на вопрос здесь: поле ForeignKey с основными отношениями, которое я попросил несколько дней назад. Поместите Boolean на Player, который указывает капитана, и поставьте несколько предварительных скинов, которые подтверждают, что каждая команда должна иметь одного и того же капитана.

Ответ 8

Теперь можно использовать функцию AppConfig для импорта моделей:

Retailer = apps.get_model('retailers', 'Retailer')
retailer = Retailer.objects.get(id=id)