Джанго: Почему некоторые поля модели сталкиваются друг с другом? - PullRequest
168 голосов
/ 17 июля 2009

Я хочу создать объект, который содержит 2 ссылки на пользователей. Например:

class GameClaim(models.Model):
    target = models.ForeignKey(User)
    claimer = models.ForeignKey(User)
    isAccepted = models.BooleanField()

но я получаю следующие ошибки при запуске сервера:

  • Аксессор для поля 'target' конфликтует со связанным полем 'User.gameclaim_set'. Добавьте аргумент related_name в определение для target.

  • Accessor для поля 'claimer' конфликтует со связанным полем 'User.gameclaim_set' Добавьте аргумент related_name в определение для 'claimer'.

Не могли бы вы объяснить, почему я получаю ошибки и как их исправить?

Ответы [ 6 ]

288 голосов
/ 17 июля 2009

У вас есть два внешних ключа для пользователя. Django автоматически создает обратную связь между пользователем и GameClaim, которая обычно составляет gameclaim_set. Однако, поскольку у вас есть два FK, у вас будет два атрибута gameclaim_set, что, очевидно, невозможно. Поэтому вам нужно указать Django, какое имя использовать для обратного отношения.

Используйте атрибут related_name в определении FK. например,

class GameClaim(models.Model):
    target = models.ForeignKey(User, related_name='gameclaim_targets')
    claimer = models.ForeignKey(User, related_name='gameclaim_users')
    isAccepted = models.BooleanField()
8 голосов
/ 17 июля 2009

Модель User пытается создать два поля с одинаковыми именами: одно для GameClaims, которое имеет User в качестве target, и другое для GameClaims, которое имеет User как claimer. Вот документы на related_name, которые позволяют Django задавать имена атрибутов, чтобы сгенерированные автоматически не конфликтовали.

7 голосов
/ 19 августа 2010

ОП не использует абстрактный базовый класс ... но если вы это сделаете, вы обнаружите, что жесткое кодирование related_name в FK (например, ..., related_name = "myname") приведет к ряду эти конфликтные ошибки - по одной для каждого унаследованного класса от базового класса. Приведенная ниже ссылка содержит обходной путь, который прост, но определенно не очевиден.

Из документации Джанго ...

Если вы используете related_name атрибут на ForeignKey или ManyToManyField, вы должны всегда укажите уникальное обратное имя для поле. Это обычно вызывает проблема в абстрактных базовых классах, так как поля в этом классе входит в каждого ребенка классы, с одинаковыми значениями для атрибутов (в том числе related_name) каждый раз.

Подробнее здесь .

2 голосов
/ 23 августа 2017

Иногда вам нужно использовать дополнительное форматирование в related_name - фактически в любое время, когда используется наследование.

class Value(models.Model):
    value = models.DecimalField(decimal_places=2, max_digits=5)
    animal = models.ForeignKey(
        Animal, related_name="%(app_label)s_%(class)s_related")

    class Meta:
        abstract = True

class Height(Value):
    pass

class Weigth(Value):
    pass

class Length(Value):
    pass

Здесь нет конфликта, но related_name определяется один раз, и Django позаботится о создании уникальных имен отношений.

тогда у детей класса Value у вас будет доступ к:

herdboard_height_related
herdboard_lenght_related
herdboard_weight_related
0 голосов
/ 09 августа 2015

Просто добавив к ответу Джордана (спасибо за подсказку Джордан), это также может произойти, если вы импортируете уровень выше приложений, а затем импортируете приложения, например

myproject/ apps/ foo_app/ bar_app/

Так что, если вы импортируете приложения, foo_app и bar_app, вы можете получить эту проблему. У меня были приложения, foo_app и bar_app, все они перечислены в настройках.INSTALLED_APPS

И вы все равно хотите избегать импорта приложений, потому что тогда у вас одно и то же приложение установлено в 2 разных пространствах имен

apps.foo_app а также foo_app

0 голосов
/ 16 ноября 2012

Я иногда сталкиваюсь с этим, когда добавляю субмодуль в качестве приложения к проекту django, например, с учетом следующей структуры:

myapp/
myapp/module/
myapp/module/models.py

Если добавить к INSTALLED_APPS следующее:

'myapp',
'myapp.module',

Кажется, что Django дважды обрабатывает файл myapp.mymodule models.py и выдает вышеуказанную ошибку. Это можно решить, если не включить основной модуль в список INSTALLED_APPS:

'myapp.module',

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

Я наткнулся на этот пост, когда искал решение этой проблемы, поэтому решил, что я бы поставил это здесь:)

...