Ответ 1
1. На самом деле вы не наследуете наследование python, то есть вы не можете наследовать/переопределять методы или атрибуты из класса модели Place
в своем классе Restaurant
:
Например:
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
Это означает, что для получения name
в ресторане вы не можете сделать a_restaurant.name
, вам нужно будет перейти по ссылке: a_restaurant.place.name
Также обратите внимание, что при запросе объекта Place
с соответствующим Restaurant
.
a_restaurant.save()
Place.objects.get(pk=a_restaurant.pk) # won't work
Вам нужно будет написать:
a_restaurant.save()
Place.objects.get(restaurant__pk=a_restaurant.pk)
2 и 3. почти одинаковы. Вы получаете реальное наследование python с этими.
a_restaurant = Restaurant()
a_restaurant.get_x() # would actually work and print 'x'
Ваш класс модели Restaurant
наследует все от Place
: поля модели, нормальные атрибуты экземпляра/класса, менеджеры, методы... и вы также можете переопределить почти все:
Вы не можете переопределять атрибуты полей, которые не поддерживаются.
Итак, теперь вы можете напрямую получить значения полей из родительской модели: a_restaurant.name
, потому что они наследуются.
Поскольку с этой реализацией a Restaurant
является а также Place
, вы можете запросить объект Place
с данными Restaurant
:
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
Различие между 2 и 3 легче увидеть, если вы укажете другое имя в поле:
class Place(models.Model):
name = models.CharField(max_length=50)
class Restaurant(Place):
where = models.OneToOneField(Place, parent_link=True)
serves_pizza = models.BooleanField()
Работает точно так же, но для получения родительского места Restaurant
имя атрибута where
:
the_place = a_restaurant.where
с 2:
the_place = a_restaurant.place_ptr
Это означает, что place = models.OneToOneField(Place, parent_link=True)
изменит имя ссылки на экземпляр родительской модели. Имя по умолчанию '{lowercase_model_name}_ptr'
.
Последний пример:
С 1:
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]
С 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]
Надеюсь, что это поможет. Он слишком длинный:/