如何优化Django视图中的查询数量?

时间:2015-05-12 08:04:24

标签: python django

我在主题详情视图中显示评论。恰好发生了两个查询 在这个视图中:一个获取主题,一个获取评论列表。一世 了解自select_related技术无法在此使用 在视图中创建了两个不同的查询集。有没有 将查询数量减少到一个的方法?

申请代码如下。

应用程序/ models.py

class Topic(models.Model):

    headline = models.CharField(max_length=400)
    description = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    author = models.ForeignKey(User, related_name='topics')

class Comment(models.Model):

    headline = models.CharField(blank=True, max_length=400)
    description = models.TextField()
    created = models.DateTimeField(auto_now_add=True)
    modified = models.DateTimeField(auto_now=True)
    author = models.ForeignKey(User, related_name='comments')
    topic = models.ForeignKey(Topic, related_name='comments')

应用程序/ views.py

class TopicDetail(DetailView):

    queryset = Topic.objects.select_related('author').all()
    context_object_name = 'topic'

    def get_context_data(self, **kwargs):

        context = super().get_context_data(**kwargs)
        topic = self.object
        context['comments'] = topic.comments.select_related('author').all()
        return context

应用程序/模板/应用程序/ topic_detail.html

{{ topic.headline }}
{{ topic.description }}
{{ topic.created }}
{{ topic.modified }}
{{ topic.author }}
{% for comment in comments %}
    {{ comment.headline }}
    {{ comment.description }}
    {{ comment.author }}
{% endfor %}

2 个答案:

答案 0 :(得分:4)

查看反向foreignKey查找的 prefetch_related 方法。这实际上不会减少SQL查询的数量,但是django将合并python相关的注释和主题。

在文档中:https://docs.djangoproject.com/en/1.8/ref/models/querysets/#prefetch-related

此外,您应该确保为您的字段提供不同的相关名称,否则您将遇到调用它们的问题:

author = models.ForeignKey(User, related_name='user_comments')
topic = models.ForeignKey(Topic, related_name='topic_comments')

这样你就可以编写单行查询(但是2次SQL命中):

topics = Topic.objects.prefetch_related('topic_comments').select_related('author').all()

然后例如:

{% for topic in topics %}
  {% for comment in topic.topic_comments.all %}
    {{ ... }}
  {% endfor %}
{% endfor %}

答案 1 :(得分:1)

即使在纯SQL这样的"单一"查询会很难。

基本上您需要在每条评论中重复所有主题数据!就像在这个伪代码中一样:

Select comment.*, topic.*
From comments
Right Join topic

这是大量的数据处理/传输开销。整个操作应该花费更多的时间,资源然后分开查询。

如果您真的需要它,那么只需在评论主题模型中编写自定义函数,使用纯SQL。