#13839: select_related caches None for non-existent objects in reverse
one-to-one
relations
-------------------------------------+-------------------------------------
Reporter: shauncutts | Owner: lrekucki
Type: Bug | Status: new
Component: Database layer | Version: 1.2
(models, ORM) | Resolution:
Severity: Normal | Triage Stage: Accepted
Keywords: | Needs documentation: 0
Has patch: 1 | Patch needs improvement: 1
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Comment (by lrekucki):
New patch: https://github.com/django/django/pull/102
> 1. The point of selected_related() is that it avoids doing an extra
lookup. With the proposed fix, when the related object does not exist,
accessing the attribute will cause the lookup to happen. This throws the
`DoesNotExist` as it ought to, but the lookup shouldn't happen at all. I
imagine that one way to fix this, while preserving the efficiency of
select_related, is to use some other sentinel value that triggers a
`DoesNotExist` exception inside the OneToOne descriptor. (Since querysets
need to be pickled, remember that the simplest choice of sentinel value is
a class).
Added test for this. A second sentinel is not needed, because we can just
check the field.null if None is a valid value.
>
> 2. It doesn't look like it handles nullable OneToOne relations. In that
case, the None object **should** be cached.
>
Modified the current test to explicitly check a nullable OneToOneField
that it returns None
One thing to note here is that the ``null`` flag on OneToOneField is
irrelevant to this issue as it controls the other side of relation. At
least in my understanding which is:
Take two models:
{{{#!python
class Parent(Model):
pass
class Child(Model):
parent = OneToOneField(Parent)
}}}
The following is true:
1. This defines a 1-1 relation between the two with Child having a DB
field which is a non-nullable foreign key.
1. It is possible to create a Parent model, with no Child model.
1. Currently {{{ Parent.objects.select_related('child')}}} will cache None
as child value which is not correct.
1. There is no way of creating a Child model without a Parent instance (as
it is DB enforced).
1. On databases without strict FK checking, creating a Child model with an
FK pointing to non-existant Parent is possible. But {{{
Child.object.select_related('parent')}}} will result in an {{{INNER
JOIN}}} and prevent such instances of Child from being returned (is this
intentional ?).
1. Adding {{{null=true}}}, allows creating {{{Child}}} instances without a
{{{Parent}}} (it doesn't affect the reverse relation, which is declared to
be required, but isn't enforced at the DB level see 2.).
{{{Child.object.select_related('parent')}}} will return all {{{Child}}}
instances, caching None for missing {{{Parent}}}s. This is a 1?-1 (or 0-1)
relation.
Defining 1-1? (1-0) relations is subject of ticket #10227. Without that
{{{parent.child}}} should never return None.
--
Ticket URL: <https://code.djangoproject.com/ticket/13839#comment:18>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/django-updates?hl=en.