Django重复数据库查询

时间:2019-11-03 14:57:25

标签: python django django-queryset django-debug-toolbar

我正在使用django_debug_toolbar分析网页的性能。使查询结果困惑的是数据库查询。无论我做了应做的一切(我想),“结果”选项卡仍然显示重复的数据库查询警告。为了说明这个问题,我将django项目设置如下:

models.py

from django.db import models


class Question(models.Model):
    question_text = models.CharField(max_length=200)
    pub_date = models.DateTimeField('date published', auto_now_add=True)


class Choice(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE)
    choice_text = models.CharField(max_length=200)
    votes = models.IntegerField(default=0)

views.py

from django.shortcuts import render

from .models import Question, Choice


def index(request):
    return render(request, 'polls/index.html', {'questions': Question.objects.all()})

index.html

{% for question in questions %}
  <p>{{ question.question_text }}</p>
  <ul>
    {% for choice in question.choice_set.all %}
      <li>{{ choice.votes }} votes - {{ choice.choice_text }}</li>
    {% endfor %}
  </ul>
{% endfor %}

在上面的html文件和视图中,我加载了所有问题及其相关选择。为了进行测试,我只添加了2个问题,分别添加了2个和4个选择(总共6个选择)。并且django_debug_toolbar的SQL结果如下:

enter image description here

enter image description here

如何避免这些重复的SQL查询?我认为这些重复的查询可能会对大型网站的性能产生严重影响。总体上避免这些问题的方法和最佳做法是什么?

1 个答案:

答案 0 :(得分:3)

您应该.prefetch_related(..) [Django-doc]相关的Choice。然后Django将进行一次额外的查询,以一次获取所有Choice,并在Python / Django级别执行JOIN。

def index(request):
    return render(
        request,
        'polls/index.html',
        {'questions': Question.objects.prefetch_related('choice_set')}
    )