[Django] #26703: field automatically choosen as primary_key (primary_key=False do not work)

50 views
Skip to first unread message

Django

unread,
Jun 3, 2016, 3:50:39 AM6/3/16
to django-...@googlegroups.com
#26703: field automatically choosen as primary_key (primary_key=False do not work)
-------------------------------------+-------------------------------------
Reporter: nbremond | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) | Keywords: multi-table
Severity: Normal | inheritance, primary_key,
| OneToOneField
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
I tried to use multi-table inheritance with a OneToOne field to the parent
class in the child class but this field seems to be detected as
primary_key by Django (there is only one row in the database).

The field has the same type as the parent link automatically created by
Django and
the [https://docs.djangoproject.com/en/1.10/topics/db/models/#specifying-
the-parent-link-field doc on inheritance] tells that we can choose to use
a such field for the inheritance relation with `parent_link=True` but I
need the inheritance relation AND my other relation.
I tried to add `parent_link=False` but this don't change anything.
If I add `null=True` I got an error :
{{{
SystemCheckError: System check identified some issues:

ERRORS:
testapp.A.other: (fields.E007) Primary keys must not have null=True.
HINT: Set null=False on the field, or remove primary_key=True
argument.
from django.db import models
}}}
So I tried to add `primary_key=False` but that don't change anything.

There is a minimal code wich reproduce the error

models.py :
{{{
#!python
class Base(models.Model):
pass

class A(Base):
other=models.OneToOneField(Base,
parent_link=False,#do not change anything
primary_key=False,#do not change anything
null=True,#raise a SystemCheckError
related_name='other_base',
)

}}}

I can continue my project if I replace the `OneToOneField` by a
`ForeignKey` with `unique=True` but I have a warning with a hint to
replace the `ForeignKey` by a `OneToOneField` :
{{{
System check identified some issues:

WARNINGS:
testapp.A.other: (fields.W342) Setting unique=True on a ForeignKey has the
same effect as using a OneToOneField.
HINT: ForeignKey(unique=True) is usually better served by a
OneToOneField.
}}}

--
Ticket URL: <https://code.djangoproject.com/ticket/26703>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Jun 3, 2016, 8:45:43 AM6/3/16
to django-...@googlegroups.com
#26703: field automatically choosen as primary_key (primary_key=False do not work)
-------------------------------------+-------------------------------------
Reporter: nbremond | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution:
Keywords: multi-table | Triage Stage:
inheritance, primary_key, | Unreviewed
OneToOneField |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* needs_better_patch: => 0
* needs_tests: => 0
* needs_docs: => 0


Comment:

Is this a duplicate of #26320?

--
Ticket URL: <https://code.djangoproject.com/ticket/26703#comment:1>

Django

unread,
Jun 3, 2016, 8:51:58 AM6/3/16
to django-...@googlegroups.com
#26703: field automatically choosen as primary_key (primary_key=False do not work)
-------------------------------------+-------------------------------------
Reporter: nbremond | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution: duplicate

Keywords: multi-table | Triage Stage:
inheritance, primary_key, | Unreviewed
OneToOneField |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by charettes):

* status: new => closed
* resolution: => duplicate


Comment:

I'm fairly confident it is.

During the deprecation period you'll have to declare both
`OneToOneField`s:

{{{#!python
class A(Base):
base_ptr = models.OneToOneField(Base, parent_link=True,
primary_key=True)
other = models.OneToOneField(Base, null=True,
related_name='other_base')
}}}

Where the `base_ptr` field should be the named after the lower cased name
of the parent-linked base followed by the `'_ptr'` suffix.

--
Ticket URL: <https://code.djangoproject.com/ticket/26703#comment:2>

Django

unread,
Jun 3, 2016, 9:10:01 AM6/3/16
to django-...@googlegroups.com
#26703: field automatically choosen as primary_key (primary_key=False do not work)
-------------------------------------+-------------------------------------
Reporter: nbremond | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution: duplicate
Keywords: multi-table | Triage Stage:
inheritance, primary_key, | Unreviewed
OneToOneField |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by charettes):

@timgraham, It makes me wonder if we should adjust
[https://github.com/django/django/blob/44c7e5d3740edf796591ea3a89b0ff085534f225/django/db/models/options.py#L249-L252
the deprecation warning] raised on implicit non-parent_link
`OneToOneField` promotion to mention either to add `parent_link=True` or
how to declare the usual implicit `parent_link` as the actions to take in
order to have both fields available is non-trivial from the deprecation
message.

For example, in the reported case the message would be:

`Implicit parent link is deprecated, either add parent_link=True to
A.other or declare base_ptr = models.OneToOneField(Base, parent_link=True,
primary_key=True) before it during the deprecation period`

--
Ticket URL: <https://code.djangoproject.com/ticket/26703#comment:3>

Django

unread,
Jun 3, 2016, 9:42:44 AM6/3/16
to django-...@googlegroups.com
#26703: field automatically choosen as primary_key (primary_key=False do not work)
-------------------------------------+-------------------------------------
Reporter: nbremond | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution: duplicate
Keywords: multi-table | Triage Stage:
inheritance, primary_key, | Unreviewed
OneToOneField |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by timgraham):

Seems like it wouldn't hurt.

--
Ticket URL: <https://code.djangoproject.com/ticket/26703#comment:4>

Django

unread,
Jun 4, 2016, 10:40:20 AM6/4/16
to django-...@googlegroups.com
#26703: field automatically choosen as primary_key (primary_key=False do not work)
-------------------------------------+-------------------------------------
Reporter: nbremond | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution: duplicate
Keywords: multi-table | Triage Stage:
inheritance, primary_key, | Unreviewed
OneToOneField |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------

Comment (by nbremond):

Yes, this is a duplicate of #26320, sorry…
Thanks for the help !

--
Ticket URL: <https://code.djangoproject.com/ticket/26703#comment:5>

Django

unread,
Jun 4, 2016, 2:18:41 PM6/4/16
to django-...@googlegroups.com
#26703: field automatically choosen as primary_key (primary_key=False do not work)
-------------------------------------+-------------------------------------
Reporter: nbremond | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution:

Keywords: multi-table | Triage Stage:
inheritance, primary_key, | Unreviewed
OneToOneField |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by nbremond):

* status: closed => new
* resolution: duplicate =>


Comment:

I don't know if I have to reply here, on #26320 or on a new ticket, but
the solution given by charette on comment:2 does not really work.

The problem on fields is solved but I think there is still a bug during
objects instanciation.


{{{#!python
#models.py
from django.db import models

class Base(models.Model):
def __str__(self):#indicate if the object is a member of a subclass
try:
a=self.a
return "a A pk="+str(self.pk)+" (other="+str(a.other.pk)+")"
except A.DoesNotExist:
pass
try:
z=self.z
return "not a A but a Z pk="+str(self.pk)
except Z.DoesNotExist:
pass
return "not a A neither a Z pk="+str(self.pk)

class A(Base):


base_ptr = models.OneToOneField(Base, parent_link=True,
primary_key=True)

other = models.OneToOneField(Base, related_name='other_base') #I do
not have null=True

class Z(Base):
pass
}}}

I can manipulate the `Z` objects :
adding a new `Z` :
{{{#!python
>>> z=Z()
>>> z.save()
>>> Base.objects.all()
[<Base: not a A but a Z pk=1>]
}}}

if I try to do the same thing with a `A` (with a new database):

{{{#!python
>>> other=Base()
>>> other.save()
>>> a=A(other=other)
>>> a.save()
>>> a
<A: not a A neither a Z pk=None> #a is supposed to have a pk which is not
None
>>> a.other
<Base: a A pk=1 (other=1)>#other is supposed to be a base and not a A
>>> Base.objects.all()
[<Base: a A pk=1 (other=1)>]#I was expecting two objects
}}}

It seems to be possible to change a `Base` to a `A`:
{{{#!python
>>> other=Base()
>>> other.save()
>>> b=Base()
>>> b.save()
>>> Base.objects.all()
[<Base: not a A neither a Z pk=1>, <Base: not a A neither a Z pk=2>]
>>> a=A(other=other,base_ptr=b)
>>> a.save()
>>> a
<A: not a A neither a Z pk=2>#str(a) should return "a A" but this work if
we reload the object
>>> a.other
<Base: not a A neither a Z pk=1>
>>> Base.objects.all()
<Base: not a A neither a Z pk=1>, <Base: a A pk=2 (other=1)>]
}}}

This is maybe also deprecated but it can be a bug in the next version and
I didn't see a fix in [https://github.com/django/django/pull/6490 PR] (I
quickly look the pull request, maybe I'm wrong)

--
Ticket URL: <https://code.djangoproject.com/ticket/26703#comment:6>

Django

unread,
Jun 4, 2016, 8:26:46 PM6/4/16
to django-...@googlegroups.com
#26703: field automatically choosen as primary_key (primary_key=False do not work)
-------------------------------------+-------------------------------------
Reporter: nbremond | Owner: nobody
Type: Bug | Status: closed

Component: Database layer | Version: 1.9
(models, ORM) |
Severity: Normal | Resolution: duplicate

Keywords: multi-table | Triage Stage:
inheritance, primary_key, | Unreviewed
OneToOneField |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0

Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by timgraham):

* status: new => closed
* resolution: => duplicate


Comment:

Yes, a new ticket is more appropriate. #9982 may be related.

--
Ticket URL: <https://code.djangoproject.com/ticket/26703#comment:7>

Reply all
Reply to author
Forward
0 new messages