Riv*_*diz 10 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)
Run Code Online (Sandbox Code Playgroud)
查询,
books = {'books': Book.objects.filter(pk__in=Rating.objects.all().order_by('-score'
).values_list('book__id', flat=True))[:10] }
Run Code Online (Sandbox Code Playgroud)
模板,
{% for i in books %}
{{ i.title }}, {{ i.rating_set.all.first.score }} <br/>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
将模型呈现给模板,但是django调试工具栏显示为重复n次,其中n是列表中的对象数.当我使用queryset缓存时,它是正常的.
什么事后面发生,我该如何解决这个问题?
谢谢.
没有测试,但你绝对应该预取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]
Run Code Online (Sandbox Code Playgroud)
在模板中,我也怀疑.first并且.all因为它们可能会导致额外的数据库命中.此外,您不需要打电话,.first因为我们已经知道这些评级书籍至少有一个评级对象.
{% for book in books %}
{{ book.title }}, {{ book.rating_set.all.0.score }} <br/>
{% endfor %}
Run Code Online (Sandbox Code Playgroud)
更新:您需要使用rating_set.all.0而不是rating_set.0选择一流的费率
阅读select_related和prefetch_related.
Book.objects.filter(pk__in=Rating.objects.all().order_by('-score').values_list('book__id', flat=True)).preferch_related('rating_set')[:10]
Run Code Online (Sandbox Code Playgroud)
在模板中您想要访问图书评级{{ i.rating_set.all.0.score }}.每行没有select_related/ prefetch_relatedDjango进行新查询.随着prefetch_relatedDjango提出1个查询并获取所有评级.
在您的情况下,问题可能在于.first..