Django select_related() and GenericForeignKey
I have models like these:
class Comment(models.Model):
text = models.TextField(max_length = 250, blank = False)
author = models.ForeignKey(User)
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
content_object = generic.GenericForeignKey('content_type', 'object_id')
class Product(models.Model):
name = models.CharField(max_length = 40)开发者_C百科
comments = generic.GenericRelation(Comment)
In this template I show the latest 5 comments of all products:
<ul>
{% for comment in last_comments %}
<li><a href="/user/{{ comment.author }}/">{{ comment.author }}</a> on <a href="/product/{{ comment.content_object.name }}/">{{ comment.content_object }}</a>
<br>{{ comment.text }}</li>
{% endfor %}
</ul>
If I get last_comments
with last_comments = Comment.objects.all().order_by('-id')[:5]
django debug toolbar says was performed 25 queries.
If I get last_comments
with last_comments = Comment.objects.select_related().all().order_by('-id')[:5]
django debug toolbar says was performed 20 queries.
But why select_related
doesn't select the related content_object also? In django debug toolbar I see 5 queries for getting the product. And are certainly the consequence of {{ comment.content_object }}
Probably the reason is because I use GenericForeignKey in Comment
model.
Have you ideas about it?
You could try to refactor your database to look somewhat like this:
class Comment(models.Model):
...
content_object = models.ForeignKey(Content)
class Content(models.Model):
text = models.CharField(max_length=123)
class SomeSpecificContent(models.Model):
...
content = models.ForeignKey(Content)
class OtherSpecificContent(models.Model):
...
content = models.ForeignKey(Content)
which in case of Django would actually be a very similar schema to that of:
class Comment(models.Model):
...
content_object = models.ForeignKey(Content)
class Content(models.Model):
text = models.TextField()
class SomeSpecificContent(Content):
...
class OtherSpecificContent(Content):
...
as that is basically how the inheritence is handled in Django. The latter is probably less flexible and might be a little bit difficult to understand in case where SomeSpecificContent and OtherSpecificContent in fact represent totally different concepts.
Generic relations on the other hand cannot be handled efficiently exactly for this reason that they can link with whatever table you want them to. Therefore if you have a list of 5 objects it might happen, that each one of them is related to a different type of entity. Not sure how Django handles the case where 100 objects are related to 5 types of entities. Does it in fact generate 5+1 queries?
精彩评论