Opened 14 years ago

Closed 8 years ago

#11920 closed Bug (fixed)

Cannot access related field of an unsaved object if the object is from an inherited model

Reported by: zbyte64 Owned by:
Component: Database layer (models, ORM) Version: 1.1
Severity: Normal Keywords: related field doesnotexist
Cc: jp@…, david@… Triage Stage: Accepted
Has patch: no Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description

See the code below:

from django.test import TestCase
from django.db import models

class Parent(models.Model):
    pass

class Child(Parent):
    pass

class Sibling(models.Model):
    child = models.ForeignKey(Child)

class BaseLine(models.Model):
    parent = models.ForeignKey(Parent)

class RelTest(TestCase):
    def test_relation(self):
        child = Child()
        child.save()
        assert child.sibling_set, 'This will pass'
        parent = Parent()
        parent.save()
        assert parent.baseline_set, 'This will pass'
        new_parent = Parent()
        assert parent.baseline_set, 'This will pass'
        new_child = Child()
        assert new_child.sibling_set, 'This will cause an exception'
Traceback (most recent call last):
  File "/home/zbyte/Projects/bugs/bug/tests.py", line 27, in test_relation
    assert new_child.sibling_set, 'This will cause an exception'
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/related.py", line 324, in __get__
    self.related.model._default_manager.__class__)
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/related.py", line 399, in create_manager
    getattr(instance, attname)}
  File "/usr/local/lib/python2.6/dist-packages/django/db/models/fields/related.py", line 244, in __get__
    raise self.field.rel.to.DoesNotExist
DoesNotExist

As you can see this is only an issue if the model is inherited from another model. It should either return a None() queryset or this exception should be consistently raised in the other instance.

Change History (12)

comment:1 by jphoude, 14 years ago

Cc: jp@… added

comment:2 by Russell Keith-Magee, 14 years ago

milestone: 1.2
Triage Stage: UnreviewedAccepted

comment:3 by Natalia Bidart, 14 years ago

Owner: changed from nobody to Natalia Bidart
Status: newassigned

comment:4 by Natalia Bidart, 14 years ago

Even though the example is not correct (when creating the new_parent object, the old, saved parent instance is used to query the baseline_set instead of the unsaved new_parent), the problem still persists when doing:

In [1]: from fix_11920.models import *

In [2]: Parent().baseline_set
Out[2]: <django.db.models.fields.related.RelatedManager object at 0x96f936c>

In [3]: Child().sibling_set
ERROR: An unexpected error occurred while tokenizing input
The following traceback may be corrupted or invalid
The error message is: ('EOF in multi-line statement', (77, 0))

---------------------------------------------------------------------------
DoesNotExist                              Traceback (most recent call last)

/home/nessita/pycon/test_project/<ipython console> in <module>()

/home/nessita/pycon/django-sprint/lib/python2.6/site-packages/django/db/models/fields/related.pyc in __get__(self, instance, instance_type)
    352 
    353         return self.create_manager(instance,
--> 354                 self.related.model._default_manager.__class__)
    355 
    356     def __set__(self, instance, value):

/home/nessita/pycon/django-sprint/lib/python2.6/site-packages/django/db/models/fields/related.pyc in create_manager(self, instance, superclass)
    429         attname = rel_field.rel.get_related_field().name
    430         manager.core_filters = {'%s__%s' % (rel_field.name, attname):
--> 431                 getattr(instance, attname)}
    432         manager.model = self.related.model
    433 

/home/nessita/pycon/django-sprint/lib/python2.6/site-packages/django/db/models/fields/related.pyc in __get__(self, instance, instance_type)
    262                 if self.field.null:
    263                     return None
--> 264                 raise self.field.rel.to.DoesNotExist
    265             other_field = self.field.rel.get_related_field()
    266             if other_field.rel:

DoesNotExist:

comment:5 by Natalia Bidart, 14 years ago

Owner: Natalia Bidart removed
Status: assignednew

comment:6 by Russell Keith-Magee, 14 years ago

milestone: 1.21.3

Not critical for 1.2

comment:7 by David Greaves, 13 years ago

Cc: david@… added

comment:8 by Julien Phalip, 13 years ago

Severity: Normal
Type: Bug

comment:9 by Jacob, 12 years ago

milestone: 1.3

Milestone 1.3 deleted

comment:11 by Aymeric Augustin, 12 years ago

UI/UX: unset

Change UI/UX from NULL to False.

comment:12 by Aymeric Augustin, 12 years ago

Easy pickings: unset

Change Easy pickings from NULL to False.

comment:13 by Tim Graham, 8 years ago

Resolution: fixed
Status: newclosed

The provided test passes as of 5009e45dfe366ebf520eecb49d72d5a11cee1623 (Django 1.4).

Note: See TracTickets for help on using tickets.
Back to Top