kurtgn
kurtgn

Reputation: 8710

django 1.6 - get related objects of related objects

I have the following three models:

class Region(models.Model):
    code = models.IntegerField()

class ReportRequest(models.Model):
    # a report can include many regions
    regions = models.ManyToManyField(Region)

class Office(models.Model):
    # an office belongs to one region
    region =  models.ForeignKey(Region)

basically, many reports can have many regions, and one region can have many offices. How can I get all offices related to my report's regions in one query?

I can do this with two queries:

region_pks = reportrequest.regions.values_list('id', flat=True)
offices = Office.objects.filter(region_id__in=region_pks)

but I feel there must be a way to do this in just one query.

I know how to do this if this was a chain of objects connected by ForeignKeys, but ManyToManyField confuses me a bit.

update:

this way Office.objects.filter(region__in=reportrequest.regions) doesn't work.

reportrequest = ReportRequest.objects.first()
print(Office.objects.filter(region__in=reportrequest.regions).all())

Traceback (most recent call last):
  File "/Users/9999/_projects/declarator/transparency/transparency/scripts/process_report_requests.py", line 22, in <module>
    print(Office.objects.filter(region__in=reportrequest.regions).all())
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/django/db/models/manager.py", line 92, in manager_method
    return getattr(self.get_queryset(), name)(*args, **kwargs)
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/django/db/models/query.py", line 691, in filter
    return self._filter_or_exclude(False, *args, **kwargs)
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/modeltranslation/manager.py", line 338, in _filter_or_exclude
    return super(MultilingualQuerySet, self)._filter_or_exclude(negate, *args, **kwargs)
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/django/db/models/query.py", line 709, in _filter_or_exclude
    clone.query.add_q(Q(*args, **kwargs))
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1287, in add_q
    clause, require_inner = self._add_q(where_part, self.used_aliases)
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1314, in _add_q
    current_negated=current_negated, connector=connector)
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1142, in build_filter
    value, lookups = self.prepare_lookup_value(value, lookups, can_reuse)
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/django/db/models/sql/query.py", line 1047, in prepare_lookup_value
    value = value()
  File "/Users/9999/.virtualenvs/transparency/lib/python2.7/site-packages/django/db/models/fields/related.py", line 839, in __call__
    manager = getattr(self.model, kwargs.pop('manager'))
KeyError: u'manager'

Upvotes: 2

Views: 73

Answers (1)

Bipul Jain
Bipul Jain

Reputation: 4643

This

offices = Office.objects.filter(region__in=reportrequest.regions.all())

Upvotes: 1

Related Questions