alexpirine
alexpirine

Reputation: 3263

Combining prefetch_related() and only() in a Django QuerySet

I am trying to execute the following query:

ParentModel.objects.prefetch_related('child_model').only('parent_attribute', 'childs__child_atrtibute').all()

It doesn't seem to work. Django throws the following exception:

'RelatedObject' object has no attribute 'rel'

Traceback (most recent call last):
  File "/Library/Python/2.7/site-packages/django/core/handlers/base.py", line 115, in get_response
    response = callback(request, *callback_args, **callback_kwargs)
  File "/Library/Python/2.7/site-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/Library/Python/2.7/site-packages/django/contrib/auth/decorators.py", line 25, in _wrapped_view
    return view_func(request, *args, **kwargs)
  File "/Library/Python/2.7/site-packages/django/utils/decorators.py", line 91, in _wrapped_view
    response = view_func(request, *args, **kwargs)
  File "/…path_to_my_app…/models.py", line 123, in _nested_commit_on_success
    return commit_on_success(*args, **kwds)
  File "/Library/Python/2.7/site-packages/django/db/transaction.py", line 223, in inner
    return func(*args, **kwargs)
  File "/…path_to_my_app…/views.py", line 1047, in my_veiw_function
    MyParentModel.objects.prefetch_related('my_child_model').only('my_parent_attribute', 'my_child_model__my_child_attribute').all():
  File "/Library/Python/2.7/site-packages/django/db/models/query.py", line 102, in __iter__
    len(self)
  File "/Library/Python/2.7/site-packages/django/db/models/query.py", line 90, in __len__
    self._result_cache = list(self.iterator())
  File "/Library/Python/2.7/site-packages/django/db/models/query.py", line 258, in iterator
    only_load = self.query.get_loaded_field_names()
  File "/Library/Python/2.7/site-packages/django/db/models/sql/query.py", line 1888, in get_loaded_field_names
    self.deferred_to_data(collection, self.get_loaded_field_names_cb)
  File "/Library/Python/2.7/site-packages/django/db/models/sql/query.py", line 591, in deferred_to_data
    cur_model = source.rel.to
AttributeError: 'RelatedObject' object has no attribute 'rel'

If I remove the childs__child_atrtibute argument from the only() method, everything works as expected, but my query returns unnecessary data.

Django manual says we can combine only() and defer() with fields from select_related().

But is there a way to use only() with fields from prefetch_related()?

I tried to rather use ChildModel.objects.only('child_attribute').all() later in my code, but it just generates tons of queries instead of using cached results from prefetch_related().

I am using Django 1.5.

Upvotes: 3

Views: 3199

Answers (1)

ruhaib
ruhaib

Reputation: 649

I know i am probably late here and not according to the requirements of the question (Django 1.5), but in case if this helps any one...

As of Django 1.8, using Prefetch objects, this can probably be achieved as follows:

ParentModel.objects.prefetch_related(
    Prefetch(
        'child_model',
        queryset=ChildModel.objects.all().only(
             'parent_attribute', 'childs__child_atrtibute'
        )
    )
)

Upvotes: 2

Related Questions