[Django] #24936: AttributeError appears when one tries to use defer/only for a field in a model that has the reverse relationship explicitly removed

20 views
Skip to first unread message

Django

unread,
Jun 5, 2015, 10:10:38 AM6/5/15
to django-...@googlegroups.com
#24936: AttributeError appears when one tries to use defer/only for a field in a
model that has the reverse relationship explicitly removed
----------------------------------------------+--------------------
Reporter: lukawoj | Owner: nobody
Type: Bug | Status: new
Component: Database layer (models, ORM) | Version: master
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+--------------------
While investigating #24612 I discovered that if one tries to use
defer/only for a field in a model that has the reverse relationship
explicitly removed, AttributeError appears. Code changed since #24612 was
logged and now it throws following error:
{{{
AttributeError: 'ManyToOneRel' object has no attribute 'attname'
}}}

Models:
{{{
#!python
# models.py
from django.db import models
from django.contrib.auth.models import User

class Message(models.Model):
content = models.CharField(max_length=10)

class MessageParticipant(models.Model):
msg = models.ForeignKey(Message, related_name='participants')
user = models.ForeignKey(User, related_name='+')
}}}

Query to use:
{{{
list(Message.objects.all().only('participants__user__username'))
}}}

Error:
{{{
Traceback (most recent call last):
File
"C:/dev/django_con/django_sprint_2015/django_sprint/django/tests\defer\tests.py",
line 279, in test_defer_only
list(Message.objects.all().only('participants__user__username'))
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\query.py",
line 258, in __iter__
self._fetch_all()
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\query.py",
line 1063, in _fetch_all
self._result_cache = list(self.iterator())
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\query.py",
line 52, in __iter__
results = compiler.execute_sql()
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\compiler.py",
line 835, in execute_sql
sql, params = self.as_sql()
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\compiler.py",
line 384, in as_sql
extra_select, order_by, group_by = self.pre_sql_setup()
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\compiler.py",
line 48, in pre_sql_setup
self.setup_query()
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\compiler.py",
line 39, in setup_query
self.select, self.klass_info, self.annotation_col_map =
self.get_select()
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\compiler.py",
line 196, in get_select
for c in self.get_default_columns():
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\compiler.py",
line 504, in get_default_columns
only_load = self.deferred_to_columns()
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\compiler.py",
line 772, in deferred_to_columns
self.query.deferred_to_data(columns,
self.query.get_loaded_field_names_cb)
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\query.py",
line 684, in deferred_to_data
callback(target, model, values)
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\query.py",
line 1804, in get_loaded_field_names_cb
target[model] = {f.attname for f in fields}
File
"C:\dev\django_con\django_sprint_2015\django_sprint\django\django\db\models\sql\query.py",
line 1804, in <setcomp>
target[model] = {f.attname for f in fields}
AttributeError: 'ManyToOneRel' object has no attribute 'attname'
}}}

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

Django

unread,
Jun 5, 2015, 12:59:20 PM6/5/15
to django-...@googlegroups.com
#24936: AttributeError appears when one tries to use defer/only for a field in a
model that has the reverse relationship explicitly removed
-------------------------------------+-------------------------------------
Reporter: lukawoj | Owner: nobody
Type: Bug | Status: closed
Component: Database layer | Version: master
(models, ORM) |
Severity: Normal | Resolution: needsinfo
Keywords: | Triage Stage:
| Unreviewed
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
* needs_better_patch: => 0
* resolution: => needsinfo
* needs_tests: => 0
* needs_docs: => 0


Comment:

Is `only()` even supposed to work with `ManyToOneRel`?

What are you expecting
`Message.objects.only('participants__user__username')` to return since m2m
relationships are not implicitly prefetched?

What does the following yields?

{{{#!python
Message.objects.prefetch_related(
Prefetch('participants',
queryset=MessageParticipant.objects.only('user__username')),
)
}}}

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

Reply all
Reply to author
Forward
0 new messages