2016-07-19 13 views
0

После создания PROJET, то приложения и добавить это приложение к моим INSTALLED_APPS, я попытался сделать пользовательский класс пользователя по подклассам AbstractUser в моем models.py:Почему требуется изменить AUTH_USER_MODEL для подкласса AbstractUser?

from django.contrib.auth.models import AbstractUser 

class CustomUser(AbstractUser): 
    pass 

Затем я попытался запустить makemigrations, и я получил это ошибка:

SystemCheckError: System check identified some issues: 

ERRORS: 
auth.User.groups: (fields.E304) Reverse accessor for 'User.groups' clashes with reverse accessor for 'CustomUser.groups'. 
    HINT: Add or change a related_name argument to the definition for 'User.groups' or 'CustomUser.groups'. 
auth.User.user_permissions: (fields.E304) Reverse accessor for 'User.user_permissions' clashes with reverse accessor for 'CustomUser.user_permissions'. 
    HINT: Add or change a related_name argument to the definition for 'User.user_permissions' or 'CustomUser.user_permissions'. 
main.CustomUser.groups: (fields.E304) Reverse accessor for 'CustomUser.groups' clashes with reverse accessor for 'User.groups'. 
    HINT: Add or change a related_name argument to the definition for 'CustomUser.groups' or 'User.groups'. 
main.CustomUser.user_permissions: (fields.E304) Reverse accessor for 'CustomUser.user_permissions' clashes with reverse accessor for 'User.user_permissions'. 
    HINT: Add or change a related_name argument to the definition for 'CustomUser.user_permissions' or 'User.user_permissions'. 

Добавление AUTH_USER_MODEL = 'main.CustomUser' (main мое приложение), кажется, решить эту проблему (makemigrations успешно, как и migrate), но я не понимаю, почему я получаю эту ошибку даже если я просто определю этот подкласс , фактически не используя его.

Я хотел бы понять, почему эта проблема возникла на первом месте, и как это делает добавление AUTH_USER_MODEL. Я действительно не понимаю, почему это похоже на конфликт между моими CustomUser и auth.User.

ответ

1

Ваша пользовательская модель наследует AbstractUser, который является модельным классом django.contrib.auth.

AbstractUser определяет себя от AbstractBaseUser и PermissionsMixin моделей и, таким образом, связанный с моделями группы и разрешения через класс PermissionsMixin

PermissionsMixin определяет ManyToManyField отношения к Permission и Groups (что дополнительно связанное с ManyToMany с Permission) моделью, как :

class PermissionsMixin(models.Model): 
.... 

    groups = models.ManyToManyField(
     Group, 
     .... 
     related_name="user_set", 
     related_query_name="user", 
    ) 
    user_permissions = models.ManyToManyField(
     Permission, 
     .... 
     related_name="user_set", 
     related_query_name="user", 
    ) 

PermissionsMixin определяет related_name="user_set" с Permission и Group и, следовательно, модель AbstractUser имеет обратное отношение к этим моделям.

Когда подкласс AbstractUser, вы определяете две модели, которые оказывают обратную связь с Group и Permission с тем же related_name.

Но у вас не может быть двух общих или внешних ключей с одинаковыми ссылочными именами, указывающими на одну и ту же модель.

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

Поэтому в вашем приложении может быть только один подкласс AbstractUser.

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

1

Поскольку AbstractUser (или, скорее, PermissionMixin, который он наследует) определяет отношения с этими другими моделями - то есть группами, разрешениями - и использует атрибут связанного имени с жестким кодом user_set, чтобы избежать путаницы, если модель поменялась.

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

Если вы установили AUTH_USER_MODEL, то Django больше не определяет стандартный класс User; так что вы вернетесь к ситуации, когда только один класс использует это имя_соединения.

Смежные вопросы