[英]How to use select_related with GenericForeignKey in django?
[英]Django select_related() and GenericForeignKey
我有这样的模型:
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)
comments = generic.GenericRelation(Comment)
在这个模板中,我展示了所有产品的最新 5 条评论:
<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>
如果我用last_comments
last_comments = Comment.objects.all().order_by('-id')[:5]
django 得到 last_comments 调试工具栏说执行了 25 个查询。
如果我用last_comments
last_comments = Comment.objects.select_related().all().order_by('-id')[:5]
django 得到 last_comments 调试工具栏说执行了 20 个查询。
但是为什么select_related
select 也没有相关的 content_object 呢? 在 django 调试工具栏中,我看到 5 个获取产品的查询。 并且肯定是{{ comment.content_object }}
的结果
可能是因为我在Comment
model 中使用了GenericForeignKey 。
你有想法吗?
您可以尝试重构您的数据库,使其看起来像这样:
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)
在 Django 的情况下,它实际上与以下架构非常相似:
class Comment(models.Model):
...
content_object = models.ForeignKey(Content)
class Content(models.Model):
text = models.TextField()
class SomeSpecificContent(Content):
...
class OtherSpecificContent(Content):
...
因为这基本上就是在 Django 中处理继承的方式。 后者可能不太灵活,并且在 SomeSpecificContent 和 OtherSpecificContent 实际上代表完全不同的概念的情况下可能有点难以理解。
另一方面,一般关系不能被有效地处理,因为它们可以与您希望它们链接的任何表链接。 因此,如果您有一个包含 5 个对象的列表,则可能会发生每个对象都与不同类型的实体相关的情况。 不确定 Django 如何处理 100 个对象与 5 种实体相关的情况。 它实际上会生成 5+1 个查询吗?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.