2009-07-11 16 views
10

Zasadniczo mam model, w którym utworzyłem nadklasę, którą dzieli wiele innych klas, a następnie każda z tych klas ma kilka unikalnych cech, które różnią się od siebie. Powiedzmy, że klasa A jest nadklasą, a klasa B, C i D są dziećmi tej klasy.Klucze dziedziczenia modelu i obcego Django

Zarówno klasa B, jak i klasa C mogą mieć wielokrotności klasy D, jednak widziałem, że najlepiej jest umieścić relację klucza obcego w klasie D, która następnie odnosi się do jej klasy nadrzędnej. Teraz w innych językach mógłbym po prostu powiedzieć, że ma on relację ForeignKey do klasy A, a następnie język rozpoznaje prawdziwy typ klas. Jednak nie sądzę, że tak to działa z Pythonem.

Jaki jest najlepszy zalecany sposób realizacji tego problemu?

EDIT: Tutaj jest grubsza, co mam na myśli ...

class A(models.Model): 
    field = models.TextField() 

class B(A): 
    other = <class specific functionality> 

class C(A): 
    other2 = <different functionality> 

class D(A): 
    #I would like class D to have a foreign key to either B or C, but not both. 

Zasadniczo, klasa B i C Klasa obie mają wiele klasę D's. Ale konkretna klasa D należy tylko do jednego z nich.

+0

Czy możesz wyjaśnić, dlaczego potrzebujesz dziedziczenia? – Evgeny

+0

Istnieje pokrewne pytanie zawiera kilka fajnych odpowiedzi, które mogą pomóc: https://stackoverflow.com/questions/1114767/django-model-inheritance-and-foreign-keys – Miranda

Odpowiedz

3

Z Django Docs:

Na przykład, jeśli były budowanie baza „miejsc”, będzie można zbudować dość standardowe rzeczy takie jak adres, numer telefonu, itp baza danych. Następnie, jeśli chcesz zbudować bazę restauracji na szczycie miejscach, zamiast powtarzać się i replikacji tych pól w modelu restauracja, można zrobić Restauracja posiada OneToOneField do Place (ponieważ restauracji "jest" miejsce, w rzeczywistości, aby obsłużyć to, będziesz zwykle używać dziedziczenia, które obejmuje niejawną relacji jeden-do-jednego ).

Zwykle po prostu Restaurant odziedziczy po Place.Niestety, trzeba to, co uważam za Hack: odsyłający jeden-do-jednego z podklasy do nadklasy (Restaurant do Place)

+0

Czy django domyślnie nie podaje takiego odniesienia typu jeden do jednego? na przykład w przypadku modeli dziedziczonych z wielu tabel, "restaurant.place" zwraca odpowiednią instancję Place, bez potrzeby definiowania przez użytkownika żadnych relacji innych niż dziedziczenie. –

+3

może teraz, ale nie sądzę, że to miało miejsce w 2009 roku *. – geowa4

+0

Rozumiem, dziękuję! xxx –

1

widzę problemu w tym miejscu:

class D(A): 
    #D has foreign key to either B or C, but not both. 

nie mogę tego zrobić. Będziesz musiał dodać oba, ponieważ w SQL kolumny muszą być dokładnie zdefiniowane.

Nawet jeśli odziedziczone modele, takie jak Ty, zostały skompilowane z syncdb - nie zachowują się tak, jak można by oczekiwać - przynajmniej nie mogłem ich uruchomić. Nie potrafię wyjaśnić dlaczego.

ten sposób FK działa w Django

class A(models.Model): 
    a = models.CharField(max_length=5) 

class B(models.Model): 
    a = model.ForeignKey(A, related_name='A') 
    b = models.CharField(max_length=5) 

class D(models.Model): 
    a = model.ForeignKey(A, related_name='A') 
    parent = model.ForeignKey(B, related_name='D') 

ten sposób można skutecznie mieć wielokrotności D w B.

dziedziczenia w modelach (np klasa B (A)) nie działa Spodziewałbym się tego. Może ktoś inny może to lepiej wyjaśnić.

Spójrz na stronę this doc. Chodzi o relację wiele do jednego w django.

b = B() 
b.D_set.create(...) 
+0

Mój problem polega na tym, że chciałbym, aby klasa D należała do albo klasa A, albo klasa B, a nie obie. Wyjaśnię na moje pytanie. – AlbertoPL

1

Jednym ze sposobów, aby to zrobić, aby dodać klasę pośrednią, co następuje:

class A(Model): 
    class Meta(Model.Meta): 
     abstract = True 
    # common definitions here 

class Target(A): 
    # this is the target for links from D - you then need to access the 
    # subclass through ".b" or ".c" 
    # (no fields here) 

class B(Target): 
    # additional fields here 

class C(Target): 
    # additional fields here   

class D(A): 
    b_or_c = ForeignKey(Target) 
    def resolve_target(self): 
     # this does the work for you in testing for whether it is linked 
     # to a b or c instance 
     try: 
      return self.b_or_c.b 
     except B.DoesNotExist: 
      return self.b_or_c.c 

Korzystanie klasa pośrednia (cel) gwarantuje, że nie będzie tylko jeden link od D do B lub C. Czy to ma sens? Aby uzyskać więcej informacji, patrz http://docs.djangoproject.com/en/1.2/topics/db/models/#model-inheritance.

W bazie danych pojawią się tabele dla Target, B, C i D, ale nie A, ponieważ zostały one oznaczone jako abstrakcyjne (zamiast tego kolumny związane z atrybutami na A będą obecne w Target i D).

[Ostrzeżenie: w rzeczywistości nie próbowałem tego kodu - wszelkie poprawki są mile widziane!]

+0

Bardzo hacky. Nawet gdyby to działało. – clime

Powiązane problemy