2016-07-19 28 views
0

Nach einer projet erstellen, dann eine App und das Hinzufügen dieser App zu meinem INSTALLED_APPS, habe ich versucht, durch Subklassen AbstractUser in meinem models.py eine benutzerdefinierte Benutzerklasse zu machen:Warum scheint das Ändern von AUTH_USER_MODEL erforderlich zu sein, um AbstractUser abzuleiten?

from django.contrib.auth.models import AbstractUser 

class CustomUser(AbstractUser): 
    pass 

Dann habe ich versucht makemigrations und ich habe dies zu laufen Fehler:

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'. 

Hinzufügen AUTH_USER_MODEL = 'main.CustomUser' (main ist meine app) scheint dieses Problem zu lösen (makemigrations gelingt es, genau wie migrate), aber ich weiß nicht bekommen, warum ich diesen Fehler sogar wenn ich nur diese Unterklasse definiere, ohne sie tatsächlich zu benutzen,.

Ich würde gerne verstehen, warum dieses Problem an erster Stelle aufgetreten ist, und wie fügt das Hinzufügen AUTH_USER_MODEL es zu lösen. Ich verstehe nicht wirklich, warum es so aussieht, als gäbe es einen Konflikt zwischen meinem CustomUser und auth.User.

Antwort

1

Ihr benutzerdefiniertes Benutzermodell erbt AbstractUser. Dies ist eine Modellklasse von django.contrib.auth.

AbstractUser definiert sich aus AbstractBaseUser und PermissionsMixin Modelle und ist somit mit den Gruppen und Berechtigungsmodelle über PermissionsMixin Klasse

PermissionsMixin definiert eine ManyToManyField Beziehung zu Permission und Groups (die weiteren verwandten ManyToMany mit den Permission) -Modelle im Zusammenhang wie :

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 definiert related_name="user_set" mit der Permission und Group Modelle und damit die AbstractUser Modell hat umgekehrte Beziehung zu diesen Modellen.

Wenn Sie die AbstractUser Unterklasse definiert man zwei Modelle, die mit Group und Permission mit derselben related_name umgekehrte Beziehung haben.

Aber Sie können nicht zwei generische oder fremde Schlüssel mit identischen verwandten Namen haben, die auf dasselbe Modell verweisen.

Sie müssen immer einen eindeutigen umgekehrten Namen und einen Abfragenamen für das Feld angeben.Dies würde normalerweise ein Problem in abstrakten Basisklassen verursachen, da die Felder in dieser Klasse in jeder der untergeordneten Klassen enthalten sind, mit genau denselben Werten für die Attribute.

Daher können Sie nur eine Unterklasse von AbstractUser in Ihrer Anwendung haben.

Wenn Sie die Klasse AbstractUser ableiten, müssen Sie dieses untergeordnete Modell auf AUTH_USER_MODEL verweisen, damit Ihre Anwendung auf genau eine Instanz eines AbstractUser und nicht auf zwei Instanzen zeigt.

1

Weil AbstractUser (oder vielmehr die PermissionMixin, von der er erbt) Beziehungen zu diesen anderen Modellen definiert - dh Gruppen, Berechtigungen - und verwendet ein fest codiertes Attribut related_name, user_set, um Verwirrung zu vermeiden, wenn das Modell ausgelagert wird.

Das ist in Ordnung, solange die Klasse abstrakt bleibt, aber sobald Sie eine konkrete Unterklasse definieren, wird Django die umgekehrten Beziehungen zu diesem Modell definieren; Jetzt haben Sie zwei Modelle, die denselben Wert user_set als den verwandten Namen aus Gruppe verwenden.

Wenn Sie AUTH_USER_MODEL festlegen, definiert Django nicht mehr die standardmäßige Benutzerklasse. Sie befinden sich also wieder in der Situation, in der nur eine Klasse diesen related_name verwendet.