是否可以优化Django,以便不会在类似的事情上运行这么多查询
for student in Student.objects.all():
for course in student.course_set.all():
for grade in course.grade_set.filter(student=student):
# do stuff
查询数量是学生*课程*等级,这些等级可能会变得很大。
*编辑 从roseman的博客中获得一些想法之后的一种可能性。
for grade in student.grade_set.order_by('course', 'marking_period').select_related():
if grade.marking_period_id in some_report_input:
# do stuff
这只是一个片段,但基本上我用for循环替换了for循环,我关心的最后一项(成绩)成绩引用了我需要的一切(学生,课程,标记期)。使用诸如marking_period_id之类的东西而不是grade.marking_period(进行另一个查询)是关键。
折衷是代码可读性。我想过滤掉成绩并根据标准进行整理。这从琐碎到复杂。
这绝不是一般解决方案。我确信有时候这根本无济于事。如果你知道更好的方法,请评论。
另一个例子:
for student in students:
print student
for department in departments:
print department
failed_grades = Grade.objects.filter(course__department=department,course__courseenrollment__user=student,grade__lte=70)
for failed_grade in failed_grades:
print grade.course
print grade.grade
学生报名参加课程。一门课程有一个部门。
答案 0 :(得分:1)
如果您发布模型代码和"做东西&#34>会很有帮助。你省略的代码。通过这种方式,我们可以了解如何在您的案例中进行有效的查询。
尽管如此,我认为this可能会有所帮助。它涵盖了select_related
没有的一些案例。请注意prefetch_related
自Django 1.4起可用,因此您可能需要升级到此版本才能使用它。
对我们来说,帮助您添加"做东西"这对我们非常重要。代码在这里,如果它是相关的(我认为它将是)在这里添加您的模型代码(只是字段声明将是好的)。因为获得优化查询的方式取决于模型的相关性以及如何使用查询集结果。
修改强>
为了优化最后的" for"在上一个例子中,你可以这样做:
failed_grades = Grade.objects.filter(course__department=department,course__courseenrollment__user=student,grade__lte=70).select_related('course')
for failed_grade in failed_grades:
print grade.course
print grade.grade
在此示例中,当您执行grade.course
时,该查询的select_related
部分会缓存与过滤的成绩相关的所有课程,因此您只需使用一个查询即可。因此,如果课程模型的__unicode__
方法仅使用自己的字段(我的意思是,如果您不在课程 unicode 方法中显示任何其他模型数据)您应该在示例中获得更好的性能(更少的查询)。我不确定如何根据需要改进其他语句。但我认为这可以帮助你获得你想要的东西(也许我不太了解你的模型以帮助你更好)
答案 1 :(得分:-1)
你可以使用select_related(),它只会命中一次数据库。
此链接中的更多信息(django的文档) http://docs.djangoproject.com/en/1.2/ref/models/querysets/#select-related
如何在案例中使用此
的示例for x in Student.objects.select_related():
do stuff with x.course.grade`