Opened 15 years ago
Closed 15 years ago
#12556 closed (invalid)
Django should not reset all parent model field values when saving child model with existing parent
Reported by: | Vasily Ivanov | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.1 |
Severity: | Keywords: | ||
Cc: | bas@… | Triage Stage: | Unreviewed |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Here's my model (simplified for clarity):
class Property(models.Model): area = models.IntegerField() class Restaurant(Property): num_meals = models.IntegerField() class House(Property): num_rooms = models.IntegerField() class RentedProperty(Property): rent = models.IntegerField()
Now I want to create a Restaurant object that is rented property as well. I do this:
>> rp = RentedProperty.objects.create(area=100, rent=200) >> rr = Restaurant.objects.create(num_meals=15, property_ptr=rp)
...and it fails on second line:
IntegrityError: null value in column "area" violates not-null constraint
However if I do this
>> rp = RentedProperty.objects.create(area=100, rent=200) >> rr = Restaurant.objects.create(num_meals=15, area=100, property_ptr=rp)
it works just fine.
Why am I getting an Exception first time and why should I reset all parent model properties again to save Restaurant object with existing parent RentedProperty?
Note:
See TracTickets
for help on using tickets.
I'm not convinced this is legitimate usage. There all comes down to the "composition vs inheritance" debate. To my reading, what you're trying to do shouldn't be possible, as an object can't be both a Restaurant *and* a RentedProperty. However, if you were to use composition (i.e., define a OneToOneField), then you can interrogate the Restauarant aspects and the RentedProperty aspects of a single Property object.
If you must use inheritance, there are ways you can fake what you're trying to do with raw saving (which won't save the parent class attributes), but I'm not convinced that's what the API should be doing by default.