Frage

Hope all dies macht Sinn :) Ich werde über Kommentare bei Bedarf klären. Auch experimentiere ich fett gedruckten Text in dieser Frage mit, und wird es bearbeiten, wenn ich (oder Sie) finden es abzulenken. Mit diesem aus dem Weg ...

django.contrib.auth Verwendung gibt uns von Benutzern und Gruppen, unter anderen nützlichen Dingen, die ich nicht verzichten kann (wie grundlegendes Messaging).

In meiner Anwendung habe ich mehrere verschiedene Arten von Benutzern. Ein Benutzer kann nur eine Art von sein. Das wäre leicht von Gruppen behandelt werden, mit ein wenig mehr Sorgfalt. Allerdings sind diese verschiedenen Nutzer miteinander in Beziehung in Hierarchien / Beziehungen.

nehmen Lassen Sie uns einen Blick auf diese Benutzer: -

Principals - "top level" Benutzer

Administratoren - jeder Administrator Bericht auf einen Haupt

Koordinatoren - jeder Koordinator Berichte an einen Administrator

Neben diesen gibt es andere Benutzertypen, die nicht in direktem Zusammenhang mit , kann aber später erhalten bezogen. Zum Beispiel, „Gesellschaft“ ist eine andere Art von Benutzer und haben verschiedene „Produkte“, und Produkte können durch einen „Koordinator“ überwacht werden. „Käufer“ ist eine andere Art von Benutzer, die Produkte kaufen können.

Nun sind alle diese Benutzer haben verschiedene andere Attribute, von denen einige für alle Arten von Benutzern gemeinsam sind und von denen einige unterscheiden sich nur auf einen Benutzertyp . Zum Beispiel haben alle Arten von Benutzern eine Adresse haben. Auf der anderen Seite gehört nur der Haupt Benutzer zu einer „Branch“.

Ein weiterer Punkt, der oben erwähnt wurde, ist, dass ein Benutzer immer nur von einem Typ sein kann, .

Die App auch Bedürfnisse, um zu verfolgen, die erstellt und / oder modifiziert Principals, Administratoren, Koordinatoren, Firmen, Produkte usw. . (Das ist also noch zwei Links zu dem User-Modell).

In diesem Szenario ist es eine gute Idee Djangos Multi-Table Vererbung wie folgt zu verwenden: -

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 tun, um es wie folgt vorgehen: -

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")
    #
    #
    #

Beachten Sie bitte, dass es andere Benutzer-Typen, die über Fremdschlüssel verbunden sind, 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 bin mir bewusst, dass Django verwenden hat eine Eins-zu-Eins-Beziehung für Multi-Table-Erbe hinter den Kulissen. Ich bin einfach nicht qualifiziert genug, um zu entscheiden, welche ein vernünftiger Ansatz ist.

War es hilfreich?

Lösung

Ich möchte auf die Lösung von @thornomad erweitern.

Erweitern von Djangos Benutzerklasse direkt können alle Arten von Schwierigkeiten mit den internen django.auth Mechanismen verursachen. Was ich in einer ähnlichen Situation getan ist genau das, was @thornomad schon sagt - ich mein eigenen Userprofile Modell gemacht verknüpfen Eins-zu-eins mit dem Modell Django Benutzer, in dem ich zusätzliche Benutzerdaten gehalten und von dem ich geerbt Modellen für verschiedene Arten die Nutzer.

Etwas zu passen, was Sie beschrieben:

class UserProfile(models.Model):
    user = models.OneToOneField(User, blank=True, related_name='profile')
    class Meta:
        abstract = True


class PositionHolderUserProfile(UserProfile):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    landline = models.CharField(blank=True, max_length=20)    
    mobile = models.CharField(blank=True, max_length=20)
    created_by = models.ForeignKey(PositionHolderUserProfile, editable=False, blank=True, related_name="created_users")    
    modified_by = models.ForeignKey(PositionHolderUserProfile, editable=False, blank=True, related_name="modified_users")

class Principal(PositionHolderUserProfile):
    branchoffice = models.ForeignKey(BranchOffice)

class Administrator(PositionHolderUserProfile):
    superior = models.ForeignKey(Principal, related_name="subordinates")
    province = models.ForeignKey(Province)

class Coordinator(PositionHolderUserProfile):
    superior = models.ForeignKey(Administrator, related_name="subordinates")


class Company(UserProfile):
    name = models.CharField(max_length=50)

class Product(models.Model):
    name = models.CharField(max_length=50)
    produced_by = models.ForeignKey(Company)

class Buyer(UserProfile):
    first_name = models.CharField(max_length=30)
    last_name = models.CharField(max_length=30)
    products_bought = models.ManyToManyField(Product)

Andere Tipps

Ich wechselte vor kurzem über die Modelle verwenden, die von contrib.auto.models.User erben wird. Meine allgemeine Beobachtung ist, dass in der Theorie, sie sind groß, aber manchmal sind sie nicht bekommen, auto-magisch behandelt wie sie eigentlich sind.

Ich denke, Ihre Entscheidung in Bezug auf Vererbung vs. OneToOne kommt unten zu diesem:

  • Ich will Django automatisch haben, etwas richtig 95% der Zeit zu tun, und debuggen müssen, dass andere 5%

OR -

  • Ich möchte etwas tun manuell mich 100% der Zeit

Wenn Sie es nicht gesehen haben, hat die Scott Barham Blog einen großen Beitrag zu den Benutzern vererben ab und auch eine eigene Back-End-Aufbau, um sicherzustellen, dass Ihr benutzerdefiniertes Objekt zurückgegeben wird - die Benutzer Django Erweiterung

Von Interesse wäre das AutoOneToOne Feld zur Verfügung gestellt von django-ärgerlich . Es ist eine Art Hybrid aus den beiden Ansätzen hier -. Es gibt keine Vererbung stattfindet, aber Django ist von der Erstellung der passenden OneToOneField kümmert, wenn es nicht vorhanden ist

Auch thornomad macht einen guten Punkt in Ihren Modellen über die Redundanz machen. Sie könnte leicht eine abstrakte Klasse implementieren, das zu bereinigen, wie so (vorausgesetzt, Sie manuelle OneToOne tun):

class BaseExtendedUser(models.Model):
    user = models.OneToOneField(User, blank=True, related_name='profile')
    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="created_users")    
    modified_by = models.ForeignKey(User, editable=False, blank=True, related_name="modified_users")

    class Meta:
        abstract = True

class Administrator(BaseExtendedUser):
    province = models.ForeignKey(Province)

class Principal(BaseExtendedUser):
    branchoffice = models.ForeignKey(BranchOffice)

Ich glaube nicht, dass ich das User Modell erben würde, sondern eine benutzerdefinierte UserProfile verwenden - das contrib.auth Modell allein zu lassen. Mit dem benutzerdefinierten UserProfile Modell, könnten Sie Setup eine Basis Benutzerprofil-Modell, das ein Teil aller Ihre verschiedenen Benutzertypen sein kann.

Einfach mal an es schnell, auch, ich würde aussehen sorgfältig an allen möglichen Modellen, die alle die gleichen Felder wiederholen (wie Ihre letzten beiden Principle und Administrator Modelle). die eingebaute Gruppenfunktionalität mit dem Benutzerprofil Idee Vereinigen kann tun, was Sie suchen.

Bitte beachten Sie, was im Datenmodell geschieht, wenn ein Koordinator auf einen Haupt gefördert wird. Ich würde nicht Erbe in diesem Fall überhaupt. Bitte überdenken den Vorschlag des früheren Plakat „Durch die Kombination der in Gruppenfunktionalität mit dem Benutzerprofil Idee gebaut kann tun, was Sie suchen.“

Haben Sie Objekte Ihrer Benutzerklassen müssen wie ein auth.User überall handeln? Das wäre der naheliegendste Grund für die Verwendung Vererbung über OneToOne sein. Ein Profi des OneToOne Ansatz wäre die Leichtigkeit, mit der Sie auf einen anderen User-Modell wechseln kann, wenn das ein Problem ist.

Das eigentliche Problem, das ich mit was Sie oben haben (oder die andere Methode) ist, dass es nichts scheint Sie zu stoppen von einem Hauptobjekt und ein Administrator-Objekt des gleiche Benutzer. OneToOneField kann nur garantieren, eine Eins-zu-Eins-Abbildung zwischen zwei Beziehungen.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top