Django SQL查询重复

时间:2017-06-02 14:02:13

标签: python django django-templates django-views

我有一个包含以下内容的 models.py 文件:

class Entry(models.Model):
    text = models.TextField(default='')
    time_created = models.DateTimeField(auto_now=False, auto_now_add=True)
    time_updated = models.DateTimeField(auto_now=True, auto_now_add=False)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        abstract = True
    #rest of code ...

class Question(Entry):

    def get_absolute_url(self):
        return reverse('view_question', args=[self.id])

class Answer(Entry):
    question = models.ForeignKey(Question, on_delete=models.CASCADE, default=None)

通过使用Django-debug-toolbar,我发现我正在复制许多SQL查询。

我要做的是获取最后5个问题,并在我的主页上显示它们,以及包含这些问题的答案的更多数据,提供答案的用户,该用户的化身等等。等...

我目前正在使用此views.py和home.html模板:

views.py

@login_required(login_url="accounts/login/")
def home_page(request):
    last_five = Question.objects.all().order_by('-id')[:5]
    last_five_in_ascending_order = list(reversed(last_five))
    return render(request, 'home.html', {
        'question_list': last_five_in_ascending_order,
    })

home.html的

{% for question in question_list %}
    <a href="{% url 'view_question' question.id %}">{{ question.text }}</a>
    {% if question.answer_set.all %}
        {% for answer in question.answer_set.all %}
            <img src="/media/{{ answer.created_by.userprofile.avatar }}" alt="">
            <a href="{% url 'profile' answer.created_by.id %}">
                {% firstof answer.created_by.get_full_name answer.created_by.username %}
            </a>
            {{ answer.time_passed }}
            {{ answer.text | safe }}
        {% endfor %}
    {% endif %}
{% endfor %}

如何减少对数据库的SQL查询? 我真的应该担心这些事吗?对于用户活动很少的网站,它们会有所作为吗?

1 个答案:

答案 0 :(得分:0)

你所拥有的是表继承,而不是简单的多对一关系,这使得它变得非常复杂。我真的不明白为什么像这样的简单设置需要表继承。修改像这样的模型也适用

class Entry(models.Model):
    text = models.TextField(default='')
    time_created = models.DateTimeField(auto_now=False, auto_now_add=True)
    time_updated = models.DateTimeField(auto_now=True, auto_now_add=False)
    created_by = models.ForeignKey(User, on_delete=models.CASCADE)

    class Meta:
        abstract = True
    #rest of code ...

class Question(models.Model):
    entry = models.OneToOneField(Question)
    def get_absolute_url(self):
        return reverse('view_question', args=[self.id])

class Answer(models.Model):
    question = models.ForeignKey(Question, on_delete=models.CASCADE, default=None)
    entry = models.OneToOneField(Question)

解决您正在执行的许多查询的问题。我们现在诉诸select_related

Question.objects.select_related('entry)
Answer.objects.select_related('entry', 'question')

调试工具栏现在将显示已消除重复查询。

  我应该真的担心这些事情吗?他们做了吗?   用户活动很少的网站的差异?

并非所有这些查询都试图通过其主键获取相关对象。在任何数据库中,对具有主键的单个项目的查找是O(log(N))。但对数的基数通常是一个所以你不必担心。

如果你一次性获取它们,那么当然会更快,因为你现在有一个具有更大常量的单个O(log(N))操作。但是,在小型网站上的差异是否明显是值得商榷的。