AlexW
AlexW

Reputation: 2589

django prefetch within a prefetch - must be a Model, Manager, or QuerySet, not 'QuerySet'

Im trying to do a prefetch within a prefetch in django but am getting the below error:

First argument to get_object_or_404() must be a Model, Manager, or QuerySet, not 'QuerySet'.

this is the query:

site = get_object_or_404(SiteData.objects.prefetch_related(
                                Prefetch(
                                    'sitesubnets_set',
                                    queryset=SiteSubnets.objects.filter(site_ip=True),
                                ),
                                Prefetch(
                                    'circuits_set',
                                    queryset=Circuits.objects.exclude(decommissioned=True).prefetch_related('servicecontacts_set'),
                                )
                            ),
                        pk=site_id 
                        )

if I remove the below, the query works successfully, so I know its related to chaining the prefetches im just not sure why or how to rectify this?

.prefetch_related('servicecontacts_set')

EDIT:

tried the below

site = get_object_or_404(SiteData.objects.prefetch_related(
                                Prefetch(
                                    'sitesubnets_set',
                                    queryset=SiteSubnets.objects.filter(site_ip=True),
                                ),
                                Prefetch(
                                    'circuits_set',
                                    queryset=Circuits.objects.exclude(decommissioned=True),
                                )
                            ),
                        pk=site_id 
                        )         
site.circuits_set.prefetch_related('servicecontacts_set')

error:

AttributeError: Cannot find 'servicecontacts_set' on Circuits object, 'servicecontacts_set' is an invalid parameter to prefetch_related()

service contacts is a model linked to circuits, service contacts is not linked to site data if that helps?

>>> vars(site.circuits_set.all()[0])
{'_state': <django.db.models.base.ModelState object at 0x7fa05dcf2978>, 'id': 5, 'site_data_id': 7, 'order_no': 'N/A', 'expected_install_date': datetime.date(2016, 10, 19), 'install_date': datetime.date(2016, 5, 26), 'service_contacts_id': 10, 'decommissioned': False, '_site_data_cache': <SiteData: London>}
>>>

Upvotes: 0

Views: 648

Answers (1)

Basalex
Basalex

Reputation: 1187

Well, prefetech_related is used for preventing duplicate queries and every prefetch_related arg produces extra query anyway. It follows that the using prefetch_related for a single object has no sense. So, just put it like this:

site.sitesubnets_set.prefetch_related(Prefetch(...)).filter(...)
site.circuits_set.prefetch_related(Prefetch(...)).filter(...)

It won't produce any excessive queries

Upvotes: 2

Related Questions