Django Multi-Table Inheritance VS Explizite Angabe OneToOne-Beziehung in den Modellen
Hoffe das macht Sinn 🙂 werde ich klären, über Kommentare, falls nötig. Ich bin auch Experimentieren mit fettgedruckter text in dieser Frage, und wird es Bearbeiten, wenn ich (oder du) es als störend empfinden. Mit diesem aus dem Weg...
Mit django.contrib.auth gibt uns Benutzer und Gruppe, unter andere nützliche Dinge, die ich nicht machen kann, ohne (wie basic messaging).
In meiner app habe ich mehrere verschiedene Typen von Benutzern. Ein Benutzer kann nur einen geben. Das wäre leicht behandelt werden, indem Sie Gruppen, mit ein wenig extra-Pflege. Jedoch, diese verschiedenen Benutzer sind in Bezug auf einander in Hierarchien /Beziehungen.
Lassen Sie uns nehmen einen Blick an diesen Benutzer: -
Prinzipien - "top-level-Benutzer
Administratoren - jeder administrator meldet ein AUFTRAGGEBER
- Koordinatoren der einzelnen Koordinator berichtet an den Administrator
Abgesehen von diesen gibt es andere Benutzer gibt, die nicht direkt mit, kann aber für ähnliche, später. Zum Beispiel, "die Firma" ist eine andere Art von Benutzer, und kann verschiedene "Produkte", und Produkte können überwacht werden durch einen "Koordinator". "Käufer" ist eine andere Art von Benutzer kann Produkte kaufen.
Nun alle diese Benutzer haben verschiedene andere Attribute, von denen einige gemeinsam sind, alle Arten von Benutzern und einige von denen unterscheiden, die nur einem Benutzer geben. Zum Beispiel, alle Arten von Benutzern haben eine Adresse. Auf der anderen Seite, nur die Wichtigsten Benutzer gehört zu einer "BranchOffice".
Weiterer Punkt, der bereits oben angeführt, ist, dass ein Benutzer kann immer nur von einem Typ.
Die app auch Bedürfnisse zu verfolgen, erstellt und/oder modifiziert, Schulleiter, Administratoren, Koordinatoren, Unternehmen, Produkte etc.. (So dass zwei weitere links zu dem Benutzer-Modell.)
In diesem Szenario, ist es eine gute Idee, Django ' s multi-table inheritance wie folgt: -
from django.contrib.auth.models import User
class Principal(User):
#
#
#
branchoffice = models.ForeignKey(BranchOffice)
landline = models.CharField(blank=True, max_length=20)
mobile = models.CharField(blank=True, max_length=20)
created_by = models.ForeignKey(User, editable=False, blank=True, related_name="principalcreator")
modified_by = models.ForeignKey(User, editable=False, blank=True, related_name="principalmodifier")
#
#
#
Oder sollte ich gehen, es zu tun mögen dieses: -
class Principal(models.Model):
#
#
#
user = models.OneToOneField(User, blank=True)
branchoffice = models.ForeignKey(BranchOffice)
landline = models.CharField(blank=True, max_length=20)
mobile = models.CharField(blank=True, max_length=20)
created_by = models.ForeignKey(User, editable=False, blank=True, related_name="principalcreator")
modified_by = models.ForeignKey(User, editable=False, blank=True, related_name="principalmodifier")
#
#
#
Bitte beachten Sie, dass es andere Benutzer gibt, die über foreign keys, zum Beispiel: -
class Administrator(models.Model):
#
#
#
principal = models.ForeignKey(Principal, help_text="The supervising principal for this Administrator")
user = models.OneToOneField(User, blank=True)
province = models.ForeignKey( Province)
landline = models.CharField(blank=True, max_length=20)
mobile = models.CharField(blank=True, max_length=20)
created_by = models.ForeignKey(User, editable=False, blank=True, related_name="administratorcreator")
modified_by = models.ForeignKey(User, editable=False, blank=True, related_name="administratormodifier")
Ich mir bewusst bin, dass Django nicht eine eins-zu-eins-Beziehung für multi-table inheritance hinter die kulissen. Ich bin einfach nicht qualifiziert genug zu entscheiden, was einem mehr sound Ansatz.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Ich würde gerne erweitern auf die Lösung von @thornomad.
Ausweitung der Django User-Klasse kann direkt dazu führen, dass alle Arten von Schwierigkeiten mit der internen django.auth-Mechanismen. Was ich getan habe, in einer ähnlichen situation ist genau das, was @thornomad schlägt - ich habe meine eigene UserProfile Modell verknüpften eins-zu-eins mit der Django-User-Modell, in dem hielt ich zusätzliche user-Daten und von dem ich geerbt Modelle für verschiedene Arten von Benutzern.
Etwas zu passen, was du beschrieben hast:
CommandError: One or more models did not validate: app1.positionholderuserprofile: Accessor for field 'user' clashes with related field 'User.profile'. Add a related_name argument to the definition for 'user'.
Ich habe vor kurzem umgeschaltet, um mit Hilfe von Modellen, die Erben aus der contrib.auto.Modelle.Benutzer. Meine Allgemeine Beobachtung ist, dass in der Theorie Sie sind groß, aber manchmal Sie nicht bekommen, die auto-magisch behandelt, wie Sie es sollten.
Ich denke, deine Entscheidung bezüglich der Vererbung vs. OneToOne kommt unten zu diesem:
-ODER-
Wenn du es noch nicht gesehen haben, die Scott Barham-blog hat einen tollen post zum Erben aus User-und auch den Aufbau einer speziellen back-end um sicherzustellen, dass Ihre benutzerdefinierten Objekt zurückgegeben wird -- Die Verlängerung der Django User.
Zusätzlich von Interesse wäre die AutoOneToOne Feld durch django-das nervt. Es ist eine Art hybrid der beiden Ansätze hier-es gibt keine Vererbung stattfindet, aber Django kümmert sich um die Erstellung der passenden OneToOneField wenn es nicht vorhanden ist.
Auch, thornomad macht einen guten Punkt, um die Redundanz in Ihren Modellen. Könnte man leicht implementieren Sie eine abstrakte Klasse zu sauber, als so (vorausgesetzt, du machst das Handbuch OneToOne):
Ich glaube nicht, dass ich Erben würde die
User
- Modell, sondern verwenden Sie eine benutzerdefinierteUserProfile
- verlassen Sie diecontrib.auth
Modell allein. Mit dem customUserProfile
Modell, könnten Sie setup ein Basis Benutzer-Profil-Modell, das ein Teil sein kann von den verschiedenen Benutzer-Typen.Schaut auf Sie schnell zu, ich würde genau hinschauen, alle Modelle, alle wiederholen die gleichen Felder (wie deine letzten zwei
Principle
undAdministrator
Modelle). Die Kombination der built in-Gruppen-Funktionalität, mit der Benutzer-Profil-Idee tun können, was Sie suchen.Bitte überlegen Sie, was passiert in den Daten-Modell, wenn ein Koordinator wird gefördert AUFTRAGGEBER. Würde ich nicht verwenden-Vererbung in diesem Fall. Bitte überdenken Sie die vorherigen poster Vorschlag "durch die Kombination von built in-Gruppen-Funktionalität, mit der Benutzer-Profil-Idee tun können, was Sie suchen."
Tun, müssen Sie die Objekte Ihrer Benutzer-Klassen zu handeln, wie ein auth.Benutzer überall? Das wäre der naheliegendste Grund für die Verwendung von Vererbung gegenüber OneToOne. Ein pro der OneToOne Ansatz wäre die Leichtigkeit, mit der Sie ändern können, zu einer anderen Benutzer-Modell, wenn das ein Anliegen ist.
Das wirkliche Problem sehe ich mit dem, was Sie haben oben (durch eine Methode) ist, dass es scheint nicht zu sein, nichts hindert Sie mit einem Principal-Objekt und ein Administrator-Objekt teilen die gleichen User. OneToOneField kann nur garantieren eine eins-zu-eins-Zuordnung zwischen zwei Beziehungen.