Opened 14 years ago
Closed 14 years ago
#15993 closed Bug (duplicate)
Model multiple inheritance primary key reuse
Reported by: | Erik Wognsen | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.3 |
Severity: | Normal | Keywords: | model multiple inheritance primary key |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
This is easiest to explain with an example.
Using the following models the primary keys may be reused for unrelated objects in the Base table.
class Base(models.Model): def __unicode__(self): return '(id %d)' % (self.id) class OtherBase(models.Model): def __unicode__(self): return '(id %d)' % (self.id) class ChildOne(Base): pass class ChildTwo(OtherBase, Base): pass
Here are sessions demonstrating the behaviors with three different parentages for ChildTwo. Each session starts with a fresh database.
# With ChildTwo(Base) In [1]: from someapp.models import * In [2]: ChildOne.objects.create() Out[2]: <ChildOne: (id 1)> In [3]: ChildTwo.objects.create() Out[3]: <ChildTwo: (id 2)> In [4]: Base.objects.all() Out[4]: [<Base: (id 1)>, <Base: (id 2)>] # As expected # With ChildTwo(Base, OtherBase) In [1]: from someapp.models import * In [2]: ChildOne.objects.create() Out[2]: <ChildOne: (id 1)> In [3]: ChildTwo.objects.create() Out[3]: <ChildTwo: (id 2)> In [4]: Base.objects.all() Out[4]: [<Base: (id 1)>, <Base: (id 2)>] In [5]: OtherBase.objects.all() Out[5]: [<OtherBase: (id 2)>] # As expected # With ChildTwo(OtherBase, Base) In [1]: from someapp.models import * In [2]: ChildOne.objects.create() Out[2]: <ChildOne: (id 1)> In [3]: ChildTwo.objects.create() Out[3]: <ChildTwo: (id 1)> In [4]: Base.objects.all() Out[4]: [<Base: (id 1)>] In [5]: OtherBase.objects.all() Out[5]: [<OtherBase: (id 1)>] # Not expected, the two objects share the id! # With ChildTwo(OtherBase, Base), creating a ChildTwo instance first In [1]: from someapp.models import * In [2]: ChildTwo.objects.create() Out[2]: <ChildTwo: (id 1)> In [3]: ChildOne.objects.create() Out[3]: <ChildOne: (id 2)> In [4]: Base.objects.all() Out[4]: [<Base: (id 1)>, <Base: (id 2)>] In [5]: OtherBase.objects.all() Out[5]: [<OtherBase: (id 1)>] # As expected # Continuing... In [6]: ChildTwo.objects.create() Out[6]: <ChildTwo: (id 2)> # Again, an id reuse.
In general the ChildTwo creation just picks the next available id in OtherBase without checking if it's free in Base.
This was observed using Django 1.3.0 and behavior was the same for both sqlite3 (3.7.2) and mysql (5.1.49).
This looks like a dupe of #12002.