Django select_related()和GenericForeignKey

时间:2011-07-20 00:13:28

标签: python django

我有这样的模特:

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调试工具栏,则表示执行了25次查询。

如果last_comments使用last_comments = Comment.objects.select_related().all().order_by('-id')[:5] django调试工具栏,则表示已执行了20次查询。

但为什么select_related也没有选择相关的content_object呢?在django调试工具栏中,我看到5个获取产品的查询。肯定是{{ comment.content_object }}

的结果

原因可能是因为我在Comment模型中使用 GenericForeignKey

你有什么想法吗?

1 个答案:

答案 0 :(得分:-1)

您可以尝试重构数据库,使其看起来像这样:

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个查询吗?