为什么修改AUTH_USER_MODEL似乎需要继承AbstractUser?

时间:2016-07-19 15:47:45

标签: django django-migrations django-custom-user

创建专业版,然后是应用并将此应用添加到我的INSTALLED_APPS后,我尝试通过在AbstractUser中继承models.py来创建自定义用户类:

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如何解决它。我真的不明白为什么我的CustomUserauth.User之间存在冲突。

2 个答案:

答案 0 :(得分:2)

您的自定义用户模型会继承AbstractUser,这是django.contrib.auth的模型类。

AbstractUserAbstractBaseUserPermissionsMixin模型定义自己,因此通过PermissionsMixin类与组和权限模型相关

PermissionsMixin定义与ManyToManyFieldPermission的{​​{1}}关系(与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", ) 使用PermissionsMixinrelated_name="user_set"模型定义Permission,因此Group模型与这些模型具有反向关系。

当您继承AbstractUser时,您定义了两个与AbstractUserGroup具有相反关系且与Permission具有相反关系的模型。

  

但是你不能有两个具有相同related_names的通用或外键指向同一个模型。

     

您必须始终为该字段指定唯一的反向名称和查询名称。这通常会导致抽象基类出现问题,因为此类中的字段包含在每个子类中,并且属性的值完全相同。

因此,您的应用程序中只能有一个related_name的子类。

如果您继承AbstractUser,那么您必须将该子模型指向AUTH_USER_MODEL,以便您的应用程序仅指向AbstractUser的一个实例,而不是两个。

答案 1 :(得分:1)

因为AbstractUser(或者它继承自的PermissionMixin)定义了与其他模型的关系 - 即组,权限 - 并且它使用硬编码的related_name属性user_set,以避免在模型是换掉了。

只要该类保持抽象,那就没问题了,但只要定义了一个具体的子类,Django就会定义与该模型的反向关系;现在,您有两个使用相同值user_set的模型作为Group中的相关名称。

如果设置AUTH_USER_MODEL,则Django不再定义标准User类;所以你回到只有一个类使用那个相关名称的情况。