6 Stimmen

Beziehung des Django-Modells zu mehreren Modellen

Angenommen, es gibt ein abstraktes Modell CarOwner: wobei eine Person oder ein Unternehmen ein CarOwner sein kann. Darüber hinaus kann ein Auto mit einer bestimmten VIN entweder einer Person oder einem Unternehmen gehören (in Beziehung stehen), aber nicht beiden (ausschließlicher Fall). Ganz am Ende des folgenden Codes habe ich zwei Möglichkeiten vorgestellt (siehe Kommentare im Code "# 1. SOLLTE ICH DAS HABEN???" und "# 2. ...ODER SOLLTE ICH DAS HABEN???"). In der ersten Möglichkeit wird eine Many-to-One-Beziehung zu einem abstrakten Modell hergestellt und ich bin mir nicht sicher, ob dies der richtige Weg ist. Im zweiten Fall werden zwei Beziehungen hergestellt und ich bin mir auch nicht sicher, ob das richtig ist, insbesondere ist nicht klar, wie man sie gegenseitig ausschließen kann. Also, welche ist richtig und wenn keine, bitte geben Sie die richtige Antwort, wenn Sie könnten. Danke.

class CarOwner(models.Model):
    location = models.CharField(max_length=50, blank=True)

    class Meta:
        abstract = True

class Person(CarOwner):
    name = models.CharField(max_length=50, blank=True)

class Business(CarOwner):
    business_id = models.CharField(max_length=50, blank=True)

class Car(models.Model):
    vin = models.CharField(max_length=50, blank=True)

    # 1. SOLLTE ICH DAS HABEN??? (CarOwner ist abstrakt)
    carowner = models.ForeignKey(CarOwner, blank=True, null=True)

    # 2. ...ODER SOLLTE ICH DAS HABEN???
    person = models.ForeignKey(Person, blank=True, null=True)
    business = models.ForeignKey(Business, blank=True, null=True)

9voto

zaan Punkte 887

Wie jproffitt erwähnte, könnten generische Beziehungen eine gute Lösung für Sie sein. Alternativ können Sie #2 verwenden und es sich etwas bequemer machen, indem Sie eine Eigenschaft erstellen und etwas einfache Logik hinzufügen:

class Car(models.Model):
    vin = models.CharField(max_length=50, blank=True)
    person = models.ForeignKey(Person, blank=True, null=True)
    business = models.ForeignKey(Business, blank=True, null=True)

    @property
    def carowner(self):
        return self.person or self.business

    @carowner.setter
    def carowner(self, obj):
        if type(obj) == Person:
            self.person = obj
            self.business = None
        elif type(obj) == Business:
            self.business = obj
            self.person = None
        else:
            raise ValueError("Der Objektparameter muss ein Objekt der Business- oder Person-Klasse sein")

Für Abfragen müssen Sie jedoch person oder business verwenden.

4voto

jproffitt Punkte 6245

Da CarOwner abstrakt ist, kannst du nicht #1 machen. Du könntest CarOwner konkret machen (Datenbanktabellenvererbung), und dann würde das funktionieren, aber die Tabellenvererbung bringt ihre eigenen Komplikationen mit sich. Du könntest entweder #2 machen oder einen generischen Fremdschlüssel verwenden:

carowner_content_type = models.ForeignKey(ContentType)
carowner_object_id = models.PositiveIntegerField()
carowner = generic.GenericForeignKey('carowner_content_type', 'carowner_object_id')

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X