Django SQL查询重复n次

时间:2015-11-07 20:43:02

标签: python django django-templates django-queryset

我有书模型和评级模型,

class Book(models.Model):
    title = models.CharField(max_length=255)
    slug = AutoSlugField(unique=True, populate_from='title')
    description = models.TextField()
    # more fields

class Rating(models.Model):
    book = models.ForeignKey('library.Book')
    score = models.DecimalField(max_digits=2, decimal_places=1)

查询,

books = {'books': Book.objects.filter(pk__in=Rating.objects.all().order_by('-score'
              ).values_list('book__id', flat=True))[:10] }

模板,

{% for i in books %}
   {{ i.title }}, {{ i.rating_set.all.first.score }} <br/>
{% endfor %}

将模型呈现给模板,但是django调试工具栏显示为重复n次,其中n是列表中的对象数。当我使用queryset缓存时,它是正常的。

enter image description here

后面发生了什么,我该如何解决这个问题?

感谢。

2 个答案:

答案 0 :(得分:8)

没有测试,但你绝对应该预取rating_set,以便不为每本书创建额外的数据库命中以找到他们的最高分:

rated_books = Rating.objects.all().order_by('-score').values_list('book', flat=True)
books = Book.objects.prefetch_related('rating_set').filter(pk__in=rated_books)[:10]

在模板中,我还怀疑.first.all因为它们可能会导致额外的数据库命中。此外,您无需致电.first,因为我们已经知道这些评级的图书至少有一个评级对象。

{% for book in books %}
  {{ book.title }}, {{ book.rating_set.all.0.score }} <br/>
{% endfor %}

更新:您需要使用rating_set.all.0代替rating_set.0来选择优惠费率

答案 1 :(得分:5)

了解select_relatedprefetch_related

Book.objects.filter(pk__in=Rating.objects.all().order_by('-score').values_list('book__id', flat=True)).preferch_related('rating_set')[:10]

在模板中您想要访问图书评分{{ i.rating_set.all.0.score }}。如果每行中没有select_related / prefetch_related Django,则进行新查询。使用prefetch_related Django进行了1次查询并获取所有评级。

在您的情况下,问题可能出在.first.