Django如何使这个查询更有效率

时间:2015-07-13 07:52:20

标签: python django orm

我有两种模式:

class Answer(models.Model):
    ...

class Photo(models.Model):
    name = models.CharField(...)
    answer_id = models.Foreignkey(Answer, related_name='photos')

这种关系是一对多的(一个答案有很多照片)

我需要编写一个报告功能,输出所有答案以及相应的照片。这就是我所拥有的:

def report():
    answers = Answer.objects.all()

    for answer in answers:
        result = extract_data(answer)
        for photo in answer.photos.all(): # <- executed N times, as N = # of answers in db
            result += photo.name + '\r'

        append_result_to_report(result)

这样可行,但正如您已经看到的那样,执行for photo in answer.photos.all()的次数等于数据库中的答案数。

最好,我只想执行两个db查询,一个获取所有答案,另一个获取所有照片。所以我尝试了这个:

def report():
    answers = Answer.objects.all()
    photos = list(Photo.objects.all()) # <- store the result in memory
    for answer in answers:
        result = extract_data(answer)
        for photo in photos: 
            if photo.answer_id = answer.id:
                result += photo.name + '\r'

        append_result_to_report(result)

这种方法将数据库查询的数量减少到两个,但整体执行需要更长的时间。这种方法为9.5秒,第一种方法为7.5秒。

关于如何更有效率的任何建议?

谢谢!

P.S。我正在使用Django 1.8.2

更新:我使用了@Mark Galloway建议的方法,执行时间已降至1.6秒。查询数量变为3. Django执行以下查询:

  • 从答案中选择*
  • 从照片中选择*
  • 从照片中选择*其中'(19,20,3 ...)中的'photo.answer_id'#()中的数字似乎不是连续的

我想知道上次查询的目的是什么?

2 个答案:

答案 0 :(得分:4)

通过使用prefetch_related,您可以走一对多关系,并在两个查询中获取所有照片。一个用于所有答案,另一个用于与答案相关的所有照片。

answers = Answer.objects.all().prefetch_related('photos')

for answer in answers:
    result = extract_data(answer)
    for photo in answer.photos.all(): 
        result += photo.name + '\r'

    append_result_to_report(result)

答案 1 :(得分:-1)

您需要使用select_related查询修饰符:

def report():
    # fetches answers and photos, both, at once
    answers = Answer.objects.all().select_related('photos')

    for answer in answers:
        result = extract_data(answer)
        for photo in answer.photos.all():
            result += photo.name + '\r'

        append_result_to_report(result)