简体   繁体   中英

Django prefetch_related on generic view DetailView

I have this mixin to apply prefetch_related on a view. This is the queryset that I am supposed to be working on:

MyMode.objects.all().prefetch_related('projects')

with these models:

class Workspace():
 name = models.CharField(max_length=255)
class Project():
 name = models.CharField(max_length=255)
 workspace = models.Foreignkey(Workspace)

with this mixin I created:

class PrefetchRelatedMixin(object):
    prefetch_related = None

    def get_queryset(self):
        if self.prefetch_related is None:
            raise ImproperlyConfigured(u'%(cls)s is missing the prefetch_related'
                "property. This must be a tuple or list." % {
                'cls': self.__class__.__name__})

        if not isinstance(self.prefetch_related, (tuple, list)):
            raise ImproperlyConfigured(u"%(cls)s's select_related property "
                "must be a tuple or list." % {"cls": self.__class__.__name__})

        queryset = super(PrefetchRelatedMixin, self).get_queryset()

        return queryset.prefetch_related(
            ", ".join(self.prefetch_related)
        )

called in the view like this:

class WorkspaceView(DetailView):
    prefetch_related = ['projects']
    model = Workspace

    def get_queryset(self):
        return super(WorkspaceView, self).get_queryset()

However, when I try to iterate over the related objects in my template:

{% for p in object.projects %}
    <li>{{ p.name }}</li>
{% empty %}
    <li>No Projects in this Workspace</li>
{% endfor %}

I get this error:

'RelatedManager' object is not iterable

Is there something in the mixin that altered the object for it to be returning a RelatedManager?

Thanks in advance!

@danihp has it: you need the .all .

There is also an error here:

return queryset.prefetch_related(
            ", ".join(self.prefetch_related)
        )

Should read

return queryset.prefetch_related(*self.prefetch_related)

prefetch_related takes multiple string arguments, not a single comma-separated string.

prefetch_related is the RelatedManager, you should perform method to get results:

In docs sample:

>>> pizzas = Pizza.objects.prefetch_related('toppings')
>>> [list(pizza.toppings.filter(spicy=True)) for pizza in pizzas]

For your scenario:

{% for p in object.projects.all %}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM