[Django] #23739: django 1.7.1 defer() throws AttributeError when using related_name

34 views
Skip to first unread message

Django

unread,
Oct 30, 2014, 10:51:15 PM10/30/14
to django-...@googlegroups.com
#23739: django 1.7.1 defer() throws AttributeError when using related_name
-------------------------+-------------------------------------------------
Reporter: | Owner: nobody
farhan85 | Status: new
Type: | Version: 1.7
Uncategorized | Keywords: defer related_name AttributeError
Component: | RelatedObject rel
Uncategorized | Has patch: 0
Severity: Normal | UI/UX: 0
Triage Stage: |
Unreviewed |
Easy pickings: 0 |
-------------------------+-------------------------------------------------
I have attached a simple example project, with the following Models
defined:
{{{
#!python
class ModelA(models.Model):
name = models.CharField(max_length=255)

class ModelB(models.Model):
name = models.CharField(max_length=255)
model_a = models.ForeignKey(ModelA, related_name='model_b')
}}}

Entering the following code (in a Django shell) works fine:
{{{
#!python
ModelB.objects.filter(name='').select_related('model_a').defer('model_a__name')
}}}

But when I run the following:
{{{
#!python
ModelA.objects.filter(name='').select_related('model_b').defer('model_b__name')
}}}

I get this error message:
{{{
Traceback (most recent call last):
File "<console>", line 1, in <module>
File "/home/fahammed/Documents/django_defer_bug/venv/local/lib/python2.7
/site-packages/django/db/models/query.py", line 116, in __repr__
data = list(self[:REPR_OUTPUT_SIZE + 1])
File "/home/fahammed/Documents/django_defer_bug/venv/local/lib/python2.7
/site-packages/django/db/models/query.py", line 141, in __iter__
self._fetch_all()
File "/home/fahammed/Documents/django_defer_bug/venv/local/lib/python2.7
/site-packages/django/db/models/query.py", line 966, in _fetch_all
self._result_cache = list(self.iterator())
File "/home/fahammed/Documents/django_defer_bug/venv/local/lib/python2.7
/site-packages/django/db/models/query.py", line 222, in iterator
only_load = self.query.get_loaded_field_names()
File "/home/fahammed/Documents/django_defer_bug/venv/local/lib/python2.7
/site-packages/django/db/models/sql/query.py", line 1821, in
get_loaded_field_names
self.deferred_to_data(collection, self.get_loaded_field_names_cb)
File "/home/fahammed/Documents/django_defer_bug/venv/local/lib/python2.7
/site-packages/django/db/models/sql/query.py", line 596, in
deferred_to_data
cur_model = source.rel.to
AttributeError: 'RelatedObject' object has no attribute 'rel'
}}}

Looks like defer doesn't work when you specify the related table using its
{{{related_name}}}.

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

Django

unread,
Oct 30, 2014, 11:00:13 PM10/30/14
to django-...@googlegroups.com
#23739: django 1.7.1 defer() throws AttributeError when using related_name
-------------------------------------+-------------------------------------
Reporter: farhan85 | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.7
(models, ORM) | Resolution:
Severity: Normal | Triage Stage:
Keywords: defer related_name | Unreviewed
AttributeError RelatedObject rel | Needs documentation: 0
Has patch: 0 | Patch needs improvement: 0
Needs tests: 0 | UI/UX: 0
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Changes (by farhan85):

* needs_better_patch: => 0
* type: Uncategorized => Bug
* component: Uncategorized => Database layer (models, ORM)
* needs_tests: => 0
* needs_docs: => 0


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

Django

unread,
Oct 31, 2014, 9:55:55 AM10/31/14
to django-...@googlegroups.com
#23739: django 1.7.1 defer() throws AttributeError when using related_name
-------------------------------------+-------------------------------------
Reporter: farhan85 | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 1.7
(models, ORM) | Resolution:
Severity: Release blocker | Triage Stage: Accepted
Keywords: defer related_name | Needs documentation: 0
AttributeError RelatedObject rel | Patch needs improvement: 0
Has patch: 0 | UI/UX: 0
Needs tests: 0 |
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Changes (by timgraham):

* severity: Normal => Release blocker
* stage: Unreviewed => Accepted


Comment:

This seems to be a regression present since 1.6 -- bisected to
70679243d1786e03557c28929f9762a119e3ac14. Test for Django's test suite
attached.

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

Django

unread,
Oct 31, 2014, 10:08:59 AM10/31/14
to django-...@googlegroups.com
#23739: django 1.7.1 defer() throws AttributeError when using related_name
-------------------------------------+-------------------------------------
Reporter: farhan85 | Owner: nobody
Type: | Status: new
Cleanup/optimization | Version: 1.7
Component: Database layer | Resolution:
(models, ORM) | Triage Stage: Accepted
Severity: Normal | Needs documentation: 0
Keywords: defer related_name | Patch needs improvement: 0
AttributeError RelatedObject rel | UI/UX: 0
Has patch: 0 |

Needs tests: 0 |
Easy pickings: 0 |
-------------------------------------+-------------------------------------
Changes (by akaariai):

* type: Bug => Cleanup/optimization
* severity: Release blocker => Normal


Comment:

The reason pre-1.6 didn't raise exceptions was that the chunked reads
implementation swallowed exceptions. I don't think there is a regression
here, we just get an exception instead of silently returning empty list on
error.

I tested this on Django 1.5 with the following command: `[o for o in
ModelB.objects.filter(name='').select_related('model_b').defer('model_b__name').iterator()]`.
This raises a different error (ModelB has no field named 'model_b'), but
doesn't produce any results.

We might want to allow usage of `related_name` in this context, and even
if we don't, users shouldn't get such an ugly error message.

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

Django

unread,
Nov 3, 2014, 12:44:50 AM11/3/14
to django-...@googlegroups.com
#23739: django 1.7.1 defer() throws AttributeError when using related_name
-------------------------------------+-------------------------------------
Reporter: farhan85 | Owner: nobody
Type: | Status: new
Cleanup/optimization | Version: 1.7
Component: Database layer | Resolution:
(models, ORM) | Triage Stage: Accepted
Severity: Normal | Needs documentation: 0
Keywords: defer related_name | Patch needs improvement: 0
AttributeError RelatedObject rel | UI/UX: 0
Has patch: 0 |
Needs tests: 0 |
Easy pickings: 0 |
-------------------------------------+-------------------------------------

Comment (by farhan85):

@akaariai That's not the code that was causing the error message. From
{{{ModelB.objects.filter(name='')}}}, you select the related objects from
''ModelA'' and then defer the {{{ModelA.name}}} value from the DB. So your
command should probably be:
{{{#!python
[o for o in
ModelB.objects.filter(name='').select_related('model_a').defer('model_a__name').iterator()]
}}}
Note that {{{ModelB}}} has no field called {{{model_b}}}} but it does have
a field called {{{model_a}}}.

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

Django

unread,
Nov 3, 2014, 8:06:36 AM11/3/14
to django-...@googlegroups.com
#23739: django 1.7.1 defer() throws AttributeError when using related_name
-------------------------------------+-------------------------------------
Reporter: farhan85 | Owner: nobody
Type: | Status: new
Cleanup/optimization | Version: 1.7
Component: Database layer | Resolution:
(models, ORM) | Triage Stage: Accepted
Severity: Normal | Needs documentation: 0
Keywords: defer related_name | Patch needs improvement: 0
AttributeError RelatedObject rel | UI/UX: 0
Has patch: 0 |
Needs tests: 0 |
Easy pickings: 0 |
-------------------------------------+-------------------------------------

Comment (by akaariai):

I'm confused. Using `[o for o in
ModelA.objects.filter(name='').select_related('model_b').defer('model_b__name')]`
gives me RelatedObject has no attribute rel in 1.5. Just as it does using
master. And, `[o for o in
ModelB.objects.filter(name='').select_related('model_a').defer('model_a__name').iterator()]`
works on master.

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

Django

unread,
Nov 3, 2014, 4:49:41 PM11/3/14
to django-...@googlegroups.com
#23739: django 1.7.1 defer() throws AttributeError when using related_name
-------------------------------------+-------------------------------------
Reporter: farhan85 | Owner: nobody
Type: | Status: new
Cleanup/optimization | Version: 1.7
Component: Database layer | Resolution:
(models, ORM) | Triage Stage: Accepted
Severity: Normal | Needs documentation: 0
Keywords: defer related_name | Patch needs improvement: 0
AttributeError RelatedObject rel | UI/UX: 0
Has patch: 0 |
Needs tests: 0 |
Easy pickings: 0 |
-------------------------------------+-------------------------------------

Comment (by farhan85):

I think that's because the attribute {{{model_a}}} has been explicitly
defined in the class definition of {{{ModelB}}}, whereas the class
definition of {{{ModelA}}} does not have an attribute called
{{{model_b}}}. Correct me if I'm wrong, but the {{{ModelA.model_b}}} is
dynamically created at runtime (or loaded when the value is called)?

On another (possibly) similar note, calling the {{{only()}}} function:

{{{#!python
ModelA.objects.filter(name='').select_related('model_b').only('model_b__name')
}}}

also returns the same error {{{AttributeError: 'RelatedObject' object has
no attribute 'rel'}}}, and the following line works fine:

{{{#!python
ModelB.objects.filter(name='').select_related('model_a').only('model_a__name')
}}}

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

Django

unread,
Oct 8, 2015, 8:12:17 PM10/8/15
to django-...@googlegroups.com
#23739: django 1.7.1 defer() throws AttributeError when using related_name
-------------------------------------+-------------------------------------
Reporter: farhan85 | Owner: nobody
Type: | Status: closed
Cleanup/optimization |

Component: Database layer | Version: 1.7
(models, ORM) |
Severity: Normal | Resolution: invalid
Keywords: defer related_name | Triage Stage: Accepted
AttributeError RelatedObject rel |
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: => invalid


Comment:

The problem seems to be an invalid `select_related()` query. On Django
1.9:
{{{


>>>
ModelA.objects.filter(name='').select_related('model_b').defer('model_b__name')

django.core.exceptions.FieldError: Invalid field name(s) given in
select_related: 'model_b'. Choices are: (none)
}}}
You should be using `prefech_related()` when querying reverse foreign
keys.

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

Reply all
Reply to author
Forward
0 new messages