1

プロジェクトを作成してからアプリを作成し、このアプリを my に追加した後、 myでINSTALLED_APPSサブクラス化してカスタム User クラスを作成しようとしました:AbstractUsermodels.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'( mainis my app)を追加すると、この問題が解決するようです (makemigrationsのように成功します) が、このサブクラスを実際に使用せずにmigrate定義しただけでも、このエラーが発生する理由がわかりません。

この問題が最初に発生した理由と、追加によってどのように解決されるかを理解したいと思いAUTH_USER_MODELます。CustomUserとの間に競合があるように見える理由がよくわかりませんauth.User

4

2 に答える 2

4

カスタム ユーザー モデルAbstractUserは、 のモデル クラスである を継承しdjango.contrib.authます。

AbstractUserモデルから自身を定義するため、PermissionsMixin クラスを介して Group モデルAbstractBaseUserPermissionsMixinPermission モデルに関連付けられます。

PermissionsMixinand とのManyToManyField関係を定義します(さらに ManyToMany を に関連付けます) のようなモデル:PermissionGroupsPermission

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"されているため、モデルはこれらのモデルと逆の関係にあります。PermissionGroupAbstractUser

をサブクラス化すると、同じおよびとAbstractUser逆の関係にある 2 つのモデルを定義します。GroupPermissionrelated_name

ただし、同じモデルを指す同一の related_names を持つ 2 つのジェネリック キーまたは外部キーを持つことはできません。

フィールドには常に一意の逆引き名とクエリ名を指定する必要があります。このクラスのフィールドは、属性の値がまったく同じで、各子クラスに含まれているため、これは通常、抽象基本クラスで問題を引き起こします。

したがって、アプリケーションで a のサブクラスを 1 つだけ持つことができAbstractUserます。

サブクラス化AbstractUserする場合は、その子モデルを AUTH_USER_MODEL にポイントする必要があります。これにより、Application は AbstractUser の 2 つではなく 1 つのインスタンスを正確にポイントします。

于 2016-07-19T16:34:25.610 に答える
1

AbstractUser (または継承元の PermissionMixin) は、他のモデル (つまり、グループ、権限) との関係を定義しuser_set、モデルが交換された場合の混乱を避けるために、ハードコードされた related_name 属性を使用するためです。

クラスが抽象的である限りは問題ありませんが、具体的なサブクラスを定義するとすぐに、Django はそのモデルと逆の関係を定義します。user_setこれで、Group からの関連名として同じ値 を使用する 2 つのモデルができました。

AUTH_USER_MODEL を設定すると、Django は標準の User クラスを定義しなくなります。したがって、1 つのクラスだけがその related_name を使用する状況に戻ります。

于 2016-07-19T16:04:47.573 に答える