Prefetch object with multiple levels of reverse lo

2019-07-28 03:40发布

问题:

I'm on Django 1.7 and have been using the new Prefetch objects which are a great addition. However I seem to be stuck when I need to traverse back more than one relationship. Here is my code:

    product_types = self.get_queryset().select_related().prefetch_related(
        'excise_category__exciseitem_set__unit',
        Prefetch(
            'bevtank_set__package_set__checkout_set',
            queryset=CheckOut.objects.filter(
                create_date__lte=end_date,
                submission__isnull=True,
                exempt=False),
            to_attr='checkouts_due'
        )
    )
    ...
    for pt in product_types:
        ...
        co = pt.checkouts_due
        ...

This gives me a 'ProductType' object has no attribute 'checkouts_due' on co = pt.checkouts_due. If I reduce the lookup to a single reverse lookup (for debug purposes) it works okay.

So either there is something wrong with my code, or a limitation on Prefetch. Can anyone shed some light on what might be happening here?

Thanks Nathan

回答1:

Since you're grabbing three levels deep of prefetch data, the property will exist on the level before the last one. What this means it that you'd have to do something like this to access it:

bevtank_set__package_set__checkout_set
for pt in product_types:
    for bevtank in pt.bevtank_set.all():
        for package in bevtank.package_set.all():
            co = package.checkouts_due

Django will not consolidate your prefetch across multiple relationships into a single property on the originally queried model. You have to drill down to the property that has the many-to-many or reverse FK relationship to that model you ultimately want.