What is the differences between these implementations? What does Django differently (beside inheriting Meta ordering and get_latest_by attribute) ?
# 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()
class Place(models.Model):
name = models.CharField(max_length=50)
class Restaurant(Place):
serves_pizza = models.BooleanField()
class Place(models.Model):
name = models.CharField(max_length=50)
class Restaurant(Place):
place = models.OneToOneField(Place, parent_link=True)
serves_pizza = models.BooleanField()
1. You don't really get any python inheritance, that is you can't inherit/override methods or attributes from the model class Place in your class Restaurant:
For instance:
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
This means that to obtain the name of a restaurant you can't do a_restaurant.name, you would need to follow the link: a_restaurant.place.name
Also note that when querying a Place object with the related Restaurant.
a_restaurant.save()
Place.objects.get(pk=a_restaurant.pk) # won't work
You would have to write:
a_restaurant.save()
Place.objects.get(restaurant__pk=a_restaurant.pk)
2 and 3. are almost the same. You do get real python inheritance with these.
a_restaurant = Restaurant()
a_restaurant.get_x() # would actually work and print 'x'
Your model class Restaurant inherits everything from Place: model fields, normal instance/class attributes, managers, methods... and you can also override almost anything of these:
You can't override field attributes, that's not supported.
So now you can get the values of the fields from the parent model directly:a_restaurant.name because they are inherited.
Since with these implementation a Restaurant is a also Place you can query for a Place object with Restaurant data:
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
The difference between 2 and 3 is easier to see if you give a different name to the field:
class Place(models.Model):
name = models.CharField(max_length=50)
class Restaurant(Place):
where = models.OneToOneField(Place, parent_link=True)
serves_pizza = models.BooleanField()
Works exactly the same but to obtain the parent place of a Restaurant the attribute name is where:
the_place = a_restaurant.where
with 2 would have been:
the_place = a_restaurant.place_ptr
These means that place = models.OneToOneField(Place, parent_link=True) will only change the name of the link to the parent model instance. The default name is '{lowercase_model_name}_ptr'.
Last example:
With 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]
With 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]
Hope these helps. It grow a bit too long :/
1 - to create restaurant you need to create place, after create restaurant, after link them, 2 - then creating restaurant, new place created and linked automaticaly, 3 - you renamed parent link to place.
Using Model Inheriting with Content Types you can list all Cafes, Restaurants, Bars, etc iterating on Place.objects.all()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With