【问题标题】:Why does modifying AUTH_USER_MODEL seem required to subclass AbstractUser?为什么修改 AUTH_USER_MODEL 似乎需要继承 AbstractUser?
【发布时间】:2016-07-19 15:47:44
【问题描述】:

在创建一个项目,然后是一个应用程序并将这个应用程序添加到我的INSTALLED_APPS 之后,我尝试通过在我的models.py 中继承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 是如何解决的。我真的不明白为什么我的CustomUserauth.User 之间似乎存在冲突。

【问题讨论】:

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


    【解决方案1】:

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

    AbstractUserAbstractBaseUserPermissionsMixin 模型中定义自己,因此通过 PermissionsMixin 类与 Group 和 Permission 模型相关

    PermissionsMixin 定义了 ManyToManyFieldPermissionGroups 的关系(与 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",
        )
    

    PermissionsMixinPermissionGroup 模型定义related_name="user_set",因此AbstractUser 模型与这些模型具有反向关系。

    当您对AbstractUser 进行子类化时,您定义了两个与GroupPermission 具有相同related_name 的反向关系的模型。

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

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

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

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

    【讨论】:

      【解决方案2】:

      因为 AbstractUser(或者更确切地说是它继承自的 PermissionMixin)定义了与其他模型的关系——即组、权限——并且它使用硬编码的 related_name 属性user_set,以避免在模型被换出时造成混淆.

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

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

      【讨论】:

        猜你喜欢
        • 2011-06-17
        • 2017-06-13
        • 1970-01-01
        • 1970-01-01
        • 2015-08-23
        • 1970-01-01
        • 1970-01-01
        • 2014-08-26
        • 2010-12-07
        相关资源
        最近更新 更多