【问题标题】:Django SQL query duplicated n timesDjango SQL查询重复n次
【发布时间】:2016-02-08 19:49:09
【问题描述】:

我有一个图书模型和一个评分模型,

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 调试工具栏显示为 Duplicated n 次,其中 n 是列表中对象的数量。当我使用查询集缓存时,这是正常的。

后面发生了什么,我该如何解决?

谢谢。

【问题讨论】:

    标签: python django django-templates django-queryset


    【解决方案1】:

    没有测试,但您绝对应该预取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来选择第一流

    【讨论】:

      【解决方案2】:

      了解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.

      【讨论】:

      • 没什么变化,是模板在{{ i.rating_set.all.first.score }} 部分时发生的事情
      • first改成0现在好了
      猜你喜欢
      • 2017-11-03
      • 2016-10-12
      • 2012-10-09
      • 2017-05-02
      • 2017-04-12
      • 2013-12-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多