Django model inheritance: Create a subclass using existing super class
Solution 1
Multi-table inheritance is just OneToOneField
relation between Place and Restaurant.
place = Place.objects.get(id=1)
# Create a restaurant using existing Place
restaurant = Resturant(place_ptr=place)
restaurant.save()
Solution 2
place = Place.objects.get(id=1)
# Create a restaurant using existing Place
place.__class__ = Restaurant
place.save()
restaurant = place
Solution 3
While undocumented, this seems to do the trick:
restaurant(place_ptr=place).save_base(raw=True)
This solves the problem without using any hacks and is the shortest solution, also in terms of processing, using Django APIs.
While searching for this solution, I also found a slightly longer one, but using documented APIs. It is basically the same as Mariusz answer, also see this answer for more details:
from django.forms.models import model_to_dict
restaurant(place_ptr=place, **model_to_dict(place)).save()
However, this second one is more risky due to limited field set returned by the model_to_dict (see again the answer explaining the differences among various methods presented). Naturally, it also generates more DB calls because it writes to both tables.
![michel.iamit](https://i.stack.imgur.com/3NWlq.png?s=256&g=1)
michel.iamit
As a big believer in an open society, helping each other with data and knowledge, I am a big fan of stackoverflow. Unfortunately time lacks to be very active here, but my goal is not only to get my own answers here, but help other finding theirs. Interests: ICT (no need to say here), open api's, system architecture, innovative and smart solutions, control engineering.
Updated on June 15, 2022Comments
-
michel.iamit about 2 years
I'm using multi-table-inheritance, and want to know how to create an inherited type from an instance of the superclass.
Using the example given in the documentation:
class Place(models.Model): name = models.CharField(max_length=50) address = models.CharField(max_length=80) class Restaurant(Place): serves_hot_dogs = models.BooleanField() serves_pizza = models.BooleanField()
Now when you create a
Restaurant
, you automatically make aPlace
, which is fine, and the behaviour I expect and want.But what if I make a
Place
, and later decide I want to convert to a specific type (likeRestaurant
). How do you create aRestaurant
, using an existingPlace
?