-
-
Notifications
You must be signed in to change notification settings - Fork 300
Description
Hi,
I use django-polymorphic for a personal, non-critical project, in which items (Storable) can be stored in workspaces (Workspace).
This project relies heavily on concrete inheritance, and my models all inherit from a base model (using Polymorphic).
Everything works fine but, as always with concrete inheritance, database load is quite high, especially when I want to display a list of Storable, along with their workspaces.
In order to reduce the number of queries, I'm trying to use prefetch_related('workspaces') on Storable queryset. However, while it reduces indeed the number of queries, there is a bug when come the time to display items.
I've set up a test project with the following code.
Models
from django.db import models
from polymorphic import PolymorphicModel
class Base(PolymorphicModel):
name = models.CharField('name', max_length=255, default=None, blank=True, null=True)
class Storable(Base):
pass
class Workspace(Base):
items = models.ManyToManyField(Storable, related_name="workspaces", null=True, blank=True, default = None)
View
from django.views.generic.list import ListView
from test_prefetch_related.models import Storable
class TestPrefetchRelated(ListView):
model = Storable
template_name = "test_prefetch_related/test_prefetch_related.html"
paginate_by = 10
def get_queryset(self):
return self.model.objects.all().prefetch_related('workspaces')
Template
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
{% for item in object_list %}
<h1>{{ item.name }}</h1>
<ul>
{% for w in item.workspaces.all %}
<li>{{ w.id }} - {{ w.name }}</li>
{% empty %}
None
{% endfor %}
</ul>
{% endfor %}
</body>
</html>
Database population
from test_prefetch_related.models import Storable, Workspace
# here is the code I used to populate the database with some data
# create workspaces
w1 = Workspace(name="w1")
w1.save()
w2 = Workspace(name="w2")
w2.save()
w3 = Workspace(name="w3")
w3.save()
# create storables
s1 = Storable(name="s1")
s1.save()
s1.workspaces.add(w1)
s1.save()
s2 = Storable(name="s2")
s2.save()
s2.workspaces.add(w2)
s2.save()
s3 = Storable(name="s3")
s3.save()
s3.workspaces.add(w1, w2, w3) # this storable get all workpaces
s3.save()
Html output
s1
1 - w1
1 - w1
s2
2 - w2
2 - w2
s3
3 - w3
The bug
It's hard to explain (excuse my english ;), but as you can see in output, workspaces are not displayed properly, next to each Storable. Intead, they are grouped on the first item in the queryset with which they are linked.
The expected output would be :
s1
1 - w1
s2
2 - w2
s3
1 - w1
2 - w2
3 - w3
I'm almost sure it is related to polymorphic because the following code using standard django inheritance works as expected.
In polymorphic docs, I did not found any mention of prefetch_related(). Is this behaviour one of the caveats of using concrete inheritance ? Is there anything else I could do to achieve the same result ?
You can download the code I used, if you want to check by yourself : http://seafile.eliotberriot.com/d/aca8f2399a/ (click on ZIP button in top right corner).
Thank you for your help and for this project, apart from that, I'm really happy with it !