我有一个包含以下内容的 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查询? 我真的应该担心这些事吗?对于用户活动很少的网站,它们会有所作为吗?
答案 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))操作。但是,在小型网站上的差异是否明显是值得商榷的。