Insert code generated by models using multiple inheritance is incorrect and fails in postgresql
|Reported by:||Arthur Pemberton||Owned by:||nobody|
|Component:||Database layer (models, ORM)||Version:||1.2|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||yes||Patch needs improvement:||yes|
When a model with multiple concrete parents is saved (inserted) the parents are saved first. Currently, the first parent is saved and its primary key is also set as the primary key of the yet unsaved top model. Any parent following uses the new primary key of 'self' and explicitly inserts the PK into the parent models table
There is no reason to explicitly set the PK of any of the parent classes, the code already handles retrieval of the DB assigned PK.
While other DBs let this pass, PostgreSQL does not. The problem comes not on the offending .save() but subsequent inserts to the table, this time without an explicit PK. The DB's internal counter has not advanced, so the next chosen PK already exists and yields a database error due to duplicate of a key field.
There is no apparent need to explicitly set any of the PK on insert. I believe that changing the following code block within source:django/trunk/django/db/models/base.py#13538 , line 533 , Model.save_base(...) can solve the problem:
if update_pk: setattr(self, meta.pk.attname, result)
if update_pk and cls == self.__class__: setattr(self, meta.pk.attname, result)
I have attached a sample site ('minherit') with app ('data') and a test case in a ZIP file.
Change History (15)
comment:1 Changed 6 years ago by
|Patch needs improvement:||unset|
comment:4 Changed 6 years ago by
|Patch needs improvement:||set|
|Triage Stage:||Unreviewed → Accepted|