2013-08-17 19 views
14

Jakie są różnice między tymi implementacjami? Czym różni się Django (oprócz dziedziczenia atrybutów Meta ordering i get_latest_by)?Jaka jest różnica między odziedziczonym modelem Multi-table a prostą relacją jeden-do-jednego między tymi samymi dwoma modelami?

1.

# models.py 
from django.db import models 

class Place(models.Model): 
    name = models.CharField(max_length=50) 

class Restaurant(models.Model): 
    place = models.OneToOneField(Place) 
    serves_pizza = models.BooleanField() 

2.

class Place(models.Model): 
    name = models.CharField(max_length=50) 

class Restaurant(Place): 
    serves_pizza = models.BooleanField() 

3.

class Place(models.Model): 
    name = models.CharField(max_length=50) 

class Restaurant(Place): 
    place = models.OneToOneField(Place, parent_link=True) 
    serves_pizza = models.BooleanField() 
+0

Chcę rozszerzyć strukturę wbudowanych serwisów Model witryny z dodatkowymi polami i podjęcie decyzji, która metoda jest najlepsza. – kissgyorgy

Odpowiedz

17

1. Tak naprawdę nie dostać żadnego dziedziczenia Pythona, czyli nie można dziedziczyć/metod nadpisywania lub atrybutów z klasy modelu Place w swojej klasie Restaurant:

na przykład:

class Place(models.Model): 
    name = models.CharField(max_length=50) 

    def get_x(self): 
     return 'x' 

class Restaurant(models.Model): 
    place = models.OneToOneField(Place) 
    serves_pizza = models.BooleanField() 

a_restaurant = Restaurant() 
a_restaurant.get_x() # -> wouldn't work 

oznacza to, że w celu otrzymania name z restauracji nie można zrobić a_restaurant.name, trzeba by śledzić link: a_restaurant.place.name

Należy również pamiętać, że podczas zapytań do Place obiekt z powiązanym Restaurant.

a_restaurant.save() 
Place.objects.get(pk=a_restaurant.pk) # won't work 

Trzeba by napisać:

a_restaurant.save() 
Place.objects.get(restaurant__pk=a_restaurant.pk) 

2 i 3. są prawie takie same. Otrzymujesz z nich prawdziwe dziedzictwo Pythona.

a_restaurant = Restaurant() 
a_restaurant.get_x() # would actually work and print 'x' 

Twój model klasy Restaurant dziedziczy wszystko od Place: pola modelu, normalne atrybuty instancji/klasa, menedżerów, metod ... i można również zastąpić prawie nic o nich: Nie można zastąpić atrybuty pól , to nie jest obsługiwane.

Teraz można uzyskać wartości pól bezpośrednio z modelu macierzystego: a_restaurant.name, ponieważ są one dziedziczone.

Ponieważ z tymi realizacji Restaurantjest również Place można wyszukać na Place obiektu z Restaurant danych:

a_restaurant.save() 
the_place = Place.objects.get(pk=a_restaurant.pk) 
#^this works now and returns the equivalent `Place` instance. 
the_same_restaurant = the_place.restaurant 

różnicy między 2 i 3 jest łatwiej sprawdzić, czy podasz inną nazwę pola:

class Place(models.Model): 
    name = models.CharField(max_length=50) 

class Restaurant(Place): 
    where = models.OneToOneField(Place, parent_link=True) 
    serves_pizza = models.BooleanField() 

działa dokładnie tak samo, ale w celu uzyskania miejsca rodzicem Restaurant nazwa atrybutu jest where:

the_place = a_restaurant.where 

z byłby:

the_place = a_restaurant.place_ptr 

Te środki, które place = models.OneToOneField(Place, parent_link=True) tylko zmiany nazwa odsyłacza do instancji modelu nadrzędnego. Domyślna nazwa to '{lowercase_model_name}_ptr'.


Ostatni przykład:

Z :

place1 = Place.objects.create(name='place_1') 
place2 = Place.objects.create(name='place_2') 
restaurant1 = Restaurant.objects.create(place=place1, serves_pizza=True) 

print Place.objects.all() # prints [place1, place2] 
print Restaurant.objects.all() # prints [restaurant1] 

Z 2-3:

place1 = Place.objects.create(name='place_1') 
place2 = Place.objects.create(name='place_2') 
restaurant1 = Restaurant.objects.create(name='place_3', serves_pizza=True) 

print Place.objects.all() # prints [place1, place2, place3] 
print Restaurant.objects.all() # prints [restaurant1] 

Mam nadzieję, że to pomaga. Trochę za długo rośnie:/

+0

Moja osobista opinia: opcja 2º wydaje się najlepszą implementacją tego przykładu, ponieważ "Restauracja" jest rzeczywiście "miejscem". –

+0

bardzo ładne wyjaśnienie, nie spodziewałem się tak długo :) dziękuję! – kissgyorgy

+1

Jedna wzmianka: Domyślna nazwa OneToOneField z modelu podrzędnego to 'objectname.parentobject_ptr' (not objectname.parentobject) w Django 1.5. Możesz więc zapytać o Miejsce za pomocą 'a_restaurant.place_ptr' w # 2. Ale na odwrót (zapytanie od miejsca) to: 'a_place.restaurant' – kissgyorgy

3

1 - stworzyć restaurację trzeba stworzyć miejsce, po stworzenie restauracji, po połączyć je, 2 - następnie tworzenie restauracji, nowe miejsce utworzone i połączone automatycznie, 3 - yo Zmieniono nazwę nadrzędnego linku na miejsce.

Korzystanie model Dziedziczenie typów zawartości można wymienić wszystkie kawiarnie, restauracje, bary, itp powtarzanie Place.objects.all()

Powiązane problemy