Django - Как построить подходящую промежуточную модель m2m? / лучшая практика

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

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

class Person(models.Model):
    first_name = models.CharField(max_length=64)
    last_name = models.CharField(max_length=64)
    [...]

class Team(models.Model):
    name = models.CharField(max_length=64)
    team_member_one = models.ForeignKey(Person)
    team_member_two = models.ForeignKey(Person)

class Championship(models.Model):
    name = models.CharField(max_length=128)
    status = models.BooleanField(default=True)

class Titleholder(models.Model):
    championship = models.ForeignKey(Championship)
    date_won = models.DateField(null=True,blank=True)
    date_lost = models.DateField(null=True,blank=True)
    titleholder_one = models.ForeignKey(Person,related_name='titleholder_one',null=True,blank=True)
    titleholder_two = models.ForeignKey(Person,related_name='titleholder_two',null=True,blank=True)

Чемпионаты могут быть выиграны как отдельными людьми, так и командами, в зависимости от того, одиночный это чемпионат или командный, поэтому мне пришлось использовать внешние ключи в классе Titleholder. Глядя на Django документации это просто кажется ложным. С другой стороны, мне, как новичку, промежуточная модель в примере просто никак не соответствует моей модели.

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

Помощь будет принята с благодарностью! Заранее спасибо, ребята.


person Everlong    schedule 03.05.2016    source источник
comment
Django ManyToManyField — это просто синтаксический сахар для автоматического создания и запроса промежуточной таблицы. Если вы создаете таблицу явно, как вы сделали здесь, то вам не нужно это поле (хотя оно все равно может быть полезным). Однако с представленной вами схемой возникает ряд проблем. Ни один из них не имеет ничего общего с Django, это вопрос моделирования базы данных SQL. Я предлагаю задать более общий вопрос (как я могу смоделировать эти данные? вот что я пробовал...) и пометить его тегом дизайн базы данных или моделирование данных.   -  person Kevin Christopher Henry    schedule 03.05.2016


Ответы (1)


Так что возьму с нуля. Похоже, вы немного новичок в моделировании баз данных E-R. Если бы я пытался делать то же, что и вы, я бы создавал свои модели следующим образом.

Во-первых, Team была бы моей «угловой» моделью (я использую этот термин для обозначения моделей, в которых нет полей FK), а затем в игру вступала бы модель Person следующим образом.

class Team(models.Model):
    name = models.CharField(max_length=64)

class Person(models.Model):
    first_name = models.CharField(max_length=64)
    last_name = models.CharField(max_length=64)
    team = models.ForeignKey(to=Team, null=True, blank=True, related_name='members')

Это эффективно делает модели масштабируемыми, и даже если у вас никогда не будет более двух человек в команде, это хорошая практика.

Далее идет модель Championship. Я бы связал эту модель напрямую с моделью Person как отношения «многие ко многим» со «сквозной» моделью следующим образом.

class Championship(models.Model):
    name = models.CharField(max_length=64)
    status = models.BooleanField(default=False) # This is not a great name for a field. I think should be more meaningful.
    winners = models.ManyToManyField(to=Person, related_name='championships', through='Title')

class Title(models.Model):
    championship = models.ForeignKey(to=Championship, related_name='titles')
    winner = models.ForeignKey(to=Person, related_name='titles')
    date = models.DateField(null=True, blank=True)

Я бы так и сделал, исходя из того, что я понял. Я уверен, что не понял всего, что вы пытаетесь сделать. По мере изменения моего понимания я могу модифицировать эти модели в соответствии со своими потребностями.

Другой подход, который можно использовать, заключается в использовании поля GenericForeignKey для создания поля, которое может быть FK либо для модели Team, либо для модели Person. Или еще одна вещь, которую можно изменить, может заключаться в том, что вы добавляете еще одну модель для хранения сведений о каждом чемпионате. Есть много способов сделать это, и нет ни одного правильного пути.

Дайте мне знать, если у вас есть какие-либо вопросы или что-то, с чем я не разобрался. Я постараюсь изменить ответ в соответствии с необходимостью.

person srthu    schedule 04.05.2016