Reputation: 8111
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!
Upvotes: 1
Views: 3106
Reputation: 9190
@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.
Upvotes: 3
Reputation: 51715
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 %}
Upvotes: 2