【问题标题】:Optimizing django related set average in a django rest framework serializer在 django rest 框架序列化程序中优化与 django 相关的集合平均值
【发布时间】:2015-10-05 18:13:48
【问题描述】:

我正在使用 Django 1.8 和 Django Rest Framework。 我有两个模型:MarkerMarkerComment

class Marker(models.Model):
    # a bunch of fields here...

    def rating(self):
        """
        Return the mean rating from all comments
        """
        return self.comments.aggregate(models.Avg('rating'))['rating__avg']


class MarkerComment(models.Model):
    # a few fields here...

    marker = models.ForeignKey(Marker, blank=False, related_name='comments')    
    rating = models.PositiveSmallIntegerField(blank=False)

在我的序列化程序中,我有这样的东西:

class MarkerSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = Marker
        fields = (
            'url', 'pk', 'created', 'name', 'category', 'rating', ...
        )
        read_only_fields = ('rating')

我的序列化程序上的list 查询耗时太长,因为它查询每个标记以获取平均值。见 NewRelic:

这是为我的结果集中的每个标记运行的查询:

SELECT AVG("maps_markercomment"."rating") AS "rating__avg" FROM "maps_markercomment" WHERE "maps_markercomment"."marker_id" = 1788

如果我不使用 Django Rest Framework,我可能会做一些事情来一次获得所有评分,比如

Marker.objects.filter(...).annotate(rating=Avg('comments__rating'))

所以我的问题是:我有什么选择可以让它更快?有没有办法在仍然使用序列化程序的同时将所有这些都放在一个 SQL 查询中?如何缓存每个标记的评分?

【问题讨论】:

  • 你不能对视图中的查询集应用你想要的优化吗?
  • Duh...你是对的...我已经准备好了所有元素;)我刚刚在 ViewSet 中的 get_queryset(self) 方法的末尾添加:return queryset.annotate(rating=Avg('comments__rating')) 而不是 @ 987654332@,一切都很快!
  • 随时添加您的回复作为答案,我会接受。谢谢!
  • 另外在您的查询中添加prefetch_related('comments')。它可以帮助更多:)

标签: django postgresql caching optimization django-rest-framework


【解决方案1】:

您可以将所需的优化应用到视图中的查询集,因为此优化的查询集最终将传递给序列化程序。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-02-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-12-19
    • 2013-08-21
    • 1970-01-01
    • 2017-10-03
    相关资源
    最近更新 更多