首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >优化djangos计数()方法

优化djangos计数()方法
EN

Stack Overflow用户
提问于 2016-07-01 19:17:44
回答 1查看 320关注 0票数 4

所以我有一个查询集:

代码语言:javascript
运行
复制
from django.contrib.gis.db.models.query import GeoQuerySet
from django.db import models as base_models

class RestaurantsQuerySet(GeoQuerySet):
    def get_list(self, lng, lat):
        reference_point = Point(lng, lat, srid=SRID)

        return self.annotate(rating=models.Avg('comments__rating'))\
                   .annotate(distance=Distance('location', reference_point))

    def count(self):
        return self.values('id').aggregate(count=base_models.Count('id'))['count']

我认为这个查询应该是这样的:

代码语言:javascript
运行
复制
SELECT COUNT("__col1") 
FROM (
    SELECT "restaurants_restaurant"."id" AS "__col1" 
    FROM "restaurants_restaurant" 
    GROUP BY "restaurants_restaurant"."id") subquery

而django orm则创建了这个小怪物:

代码语言:javascript
运行
复制
    SELECT COUNT("__col1") 
    FROM (
        SELECT "restaurants_restaurant"."id" AS Col1,   "restaurants_restaurant"."id" AS "__col1" 
        FROM "restaurants_restaurant" 
        LEFT OUTER JOIN "comments_comment" ON ("restaurants_restaurant"."id" = "comments_comment"."restaurant_id") 
        GROUP BY "restaurants_restaurant"."id", ST_Distance_Sphere("restaurants_restaurant"."location", 
                 ST_GeomFromEWKB('\x0101000020e61000003eb555a41d2d4b405a338d81d0a73240'::bytea
))) subquery

要调用的第一个方法是get_list。似乎django会“记住”该调用,qs被注释为ratingdistance,并将其放置到count查询中。所以我想问题是-在注释之前,我如何“重置”这个查询集到状态?

编辑:

好吧,看来我的问题还不完整。我还有一个RestaurantsList视图,定义如下:

代码语言:javascript
运行
复制
class RestaurantList(generics.ListAPIView):
    def get_queryset(self):
        return Restaurant.objects.get_list(self._lng, self._lat)

我查看了django-rest框架的内部,我看到了以下内容:

代码语言:javascript
运行
复制
class ListModelMixin(object):
    """
    List a queryset.
    """
    def list(self, request, *args, **kwargs):
        queryset = self.filter_queryset(self.get_queryset())

        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

因此,它看起来总是使用从get_queryset方法返回的查询集,并且由于它是用distancerating注释的,所以它最终被包含在count查询中。还是没有解决办法..。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2016-07-02 07:41:59

在浏览了django-rest框架代码之后,我想出了一个想法:

  1. 重写给定视图的默认Paginator类: 类RestaurantList(generics.ListAPIView):pagination_class = custom.LimitOffsetPagination
  2. 创建自定义分页类: 类LimitOffsetPagination(pagination.LimitOffsetPagination):def __init__(self):self._countable_queryset = None self._was_counted = False def was_initialized(self):返回self._countable_queryset is not def set_raw_queryset_for_count(self,queryset: QuerySet):self._countable_queryset = queryset def paginate_queryset(self,queryset,request ),view=None):self.limit =self.get_limit(请求)如果self.limit为None:返回None self.offset =self.get_offset(请求) self.count = self._countable_queryset.count() self.request = request if self.count > self.limit和self.template不是None: self.display_page_controls = True返回列表(querysetself.offset:self.offset+ self.limit)
  3. 重写视图paginator属性: @ paginator(self):paginator =.paginator(如果不是paginator.was_initialized():paginator.was_initialized返回分页器

现在,计数查询看起来会更友好一些。

代码语言:javascript
运行
复制
SELECT COUNT(*) AS "__count" FROM "restaurants_restaurant"
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/38152602

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档