Django:通过删除340个重复查询实现高效查询

Django:通过删除340个重复查询实现高效查询,django,django-views,django-queryset,Django,Django Views,Django Queryset,我每天都在绘制一组价格数据。想想白天的股票交易吧 我想做什么: class GraphView(TemplateView): def get_dates(self): dates = [] if self.get_queryset(): start = self.get_queryset()[0][2].date() end = datetime.today().date() del

我每天都在绘制一组价格数据。想想白天的股票交易吧

我想做什么:

class GraphView(TemplateView):

    def get_dates(self):
        dates = []
        if self.get_queryset():
            start = self.get_queryset()[0][2].date()
            end = datetime.today().date()
            delta = end - start
            for i in range(delta.days + 1):
                dates.append(start + timedelta(days=i))
        return dates

    def trend_line(self):
        trades = self.get_queryset()
        dates = self.get_dates()
        data_x = []
        data_y = []

        for date in dates:
            subset = trades.filter(date_of_price__date=date)
            prices_for_day = subset.aggregate(Avg('price'))
            if prices_for_day['price__avg'] > 0:
                data_x.append(date.strftime('%Y-%m-%d'))
                data_y.append(prices_for_day['price__avg'])
        return data_x, data_y

    def get_context_data(self, **kwargs):
        context = super(GraphView, self).get_context_data(**kwargs)
        x_axis_date = []
        y_axis_price = []
        bubble_text = []
        for trade in self.get_queryset():
            x_axis_date.append(trade[2].date().strftime('%Y-%m-%d'))
            y_axis_price.append(int(trade[1]))
            desc = "#%s" % (trade[0])
            bubble_text.append(str(desc.encode('ascii', 'ignore')))

        trend_data_x, trend_data_y = self.trend_line()

        try:
            x_axis_date_start = x_axis_date[0]
        except IndexError:
            x_axis_date_start = None

        try:
            x_axis_date_end = x_axis_date[-1]
        except IndexError:
            x_axis_date_end = None

        context.update({
            "x_axis_date": x_axis_date,
            "x_axis_date_start": x_axis_date_start,
            "x_axis_date_end": x_axis_date_end,
            "y_axis_price": y_axis_price,
            "bubble_text": bubble_text,
            "trend_data_x": trend_data_x,
            "trend_data_y": trend_data_y,
        })
        return context


 class ReferenceDetailView(StaffuserRequiredMixin, SetHeadlineMixin, GraphView):
        headline = "Variation Detail"
        template_name = "ref_trades/reference_detail.html"

        def get_reference_model(self):
            return get_object_or_404(ReferenceModel, pk=self.kwargs["pk"])

        def get_headline(self):
            return "%s" % self.get_reference_model()

        def get_queryset(self):
            return TradeModel.objects.filter(
                date_of_price__gte=datetime.now() - timedelta(days=365),
                reference_model__id=self.kwargs["pk"]
            ).exclude(price=0).values_list('id', 'price' , 'date_of_price', 'title')
  • 按天显示交易
  • 显示价格的平均线以显示总体趋势
问题:

class GraphView(TemplateView):

    def get_dates(self):
        dates = []
        if self.get_queryset():
            start = self.get_queryset()[0][2].date()
            end = datetime.today().date()
            delta = end - start
            for i in range(delta.days + 1):
                dates.append(start + timedelta(days=i))
        return dates

    def trend_line(self):
        trades = self.get_queryset()
        dates = self.get_dates()
        data_x = []
        data_y = []

        for date in dates:
            subset = trades.filter(date_of_price__date=date)
            prices_for_day = subset.aggregate(Avg('price'))
            if prices_for_day['price__avg'] > 0:
                data_x.append(date.strftime('%Y-%m-%d'))
                data_y.append(prices_for_day['price__avg'])
        return data_x, data_y

    def get_context_data(self, **kwargs):
        context = super(GraphView, self).get_context_data(**kwargs)
        x_axis_date = []
        y_axis_price = []
        bubble_text = []
        for trade in self.get_queryset():
            x_axis_date.append(trade[2].date().strftime('%Y-%m-%d'))
            y_axis_price.append(int(trade[1]))
            desc = "#%s" % (trade[0])
            bubble_text.append(str(desc.encode('ascii', 'ignore')))

        trend_data_x, trend_data_y = self.trend_line()

        try:
            x_axis_date_start = x_axis_date[0]
        except IndexError:
            x_axis_date_start = None

        try:
            x_axis_date_end = x_axis_date[-1]
        except IndexError:
            x_axis_date_end = None

        context.update({
            "x_axis_date": x_axis_date,
            "x_axis_date_start": x_axis_date_start,
            "x_axis_date_end": x_axis_date_end,
            "y_axis_price": y_axis_price,
            "bubble_text": bubble_text,
            "trend_data_x": trend_data_x,
            "trend_data_y": trend_data_y,
        })
        return context


 class ReferenceDetailView(StaffuserRequiredMixin, SetHeadlineMixin, GraphView):
        headline = "Variation Detail"
        template_name = "ref_trades/reference_detail.html"

        def get_reference_model(self):
            return get_object_or_404(ReferenceModel, pk=self.kwargs["pk"])

        def get_headline(self):
            return "%s" % self.get_reference_model()

        def get_queryset(self):
            return TradeModel.objects.filter(
                date_of_price__gte=datetime.now() - timedelta(days=365),
                reference_model__id=self.kwargs["pk"]
            ).exclude(price=0).values_list('id', 'price' , 'date_of_price', 'title')
当我在Django调试工具栏中查看查询时,我看到:

  • 346项查询
  • 1498.11ms
  • 查看实际的查询,我看到get_queryset()每天查询时“重复了340次”
  • 我怎样才能提高效率,避免重复?如有任何关于如何尽可能提高效率的提示/技巧,将不胜感激
方法:

class GraphView(TemplateView):

    def get_dates(self):
        dates = []
        if self.get_queryset():
            start = self.get_queryset()[0][2].date()
            end = datetime.today().date()
            delta = end - start
            for i in range(delta.days + 1):
                dates.append(start + timedelta(days=i))
        return dates

    def trend_line(self):
        trades = self.get_queryset()
        dates = self.get_dates()
        data_x = []
        data_y = []

        for date in dates:
            subset = trades.filter(date_of_price__date=date)
            prices_for_day = subset.aggregate(Avg('price'))
            if prices_for_day['price__avg'] > 0:
                data_x.append(date.strftime('%Y-%m-%d'))
                data_y.append(prices_for_day['price__avg'])
        return data_x, data_y

    def get_context_data(self, **kwargs):
        context = super(GraphView, self).get_context_data(**kwargs)
        x_axis_date = []
        y_axis_price = []
        bubble_text = []
        for trade in self.get_queryset():
            x_axis_date.append(trade[2].date().strftime('%Y-%m-%d'))
            y_axis_price.append(int(trade[1]))
            desc = "#%s" % (trade[0])
            bubble_text.append(str(desc.encode('ascii', 'ignore')))

        trend_data_x, trend_data_y = self.trend_line()

        try:
            x_axis_date_start = x_axis_date[0]
        except IndexError:
            x_axis_date_start = None

        try:
            x_axis_date_end = x_axis_date[-1]
        except IndexError:
            x_axis_date_end = None

        context.update({
            "x_axis_date": x_axis_date,
            "x_axis_date_start": x_axis_date_start,
            "x_axis_date_end": x_axis_date_end,
            "y_axis_price": y_axis_price,
            "bubble_text": bubble_text,
            "trend_data_x": trend_data_x,
            "trend_data_y": trend_data_y,
        })
        return context


 class ReferenceDetailView(StaffuserRequiredMixin, SetHeadlineMixin, GraphView):
        headline = "Variation Detail"
        template_name = "ref_trades/reference_detail.html"

        def get_reference_model(self):
            return get_object_or_404(ReferenceModel, pk=self.kwargs["pk"])

        def get_headline(self):
            return "%s" % self.get_reference_model()

        def get_queryset(self):
            return TradeModel.objects.filter(
                date_of_price__gte=datetime.now() - timedelta(days=365),
                reference_model__id=self.kwargs["pk"]
            ).exclude(price=0).values_list('id', 'price' , 'date_of_price', 'title')
我有一个视图,它继承了我创建的GraphView,用于返回所返回对象的价格图表所需的数据。由于此请求可能返回数千个结果,因此尽可能高效地执行此查询对于加载时间非常重要

使用的工具:

  • Django 1.10.1
  • 博士后
  • 以在模板中绘出结果
  • Django调试工具栏
查看和查询:

class GraphView(TemplateView):

    def get_dates(self):
        dates = []
        if self.get_queryset():
            start = self.get_queryset()[0][2].date()
            end = datetime.today().date()
            delta = end - start
            for i in range(delta.days + 1):
                dates.append(start + timedelta(days=i))
        return dates

    def trend_line(self):
        trades = self.get_queryset()
        dates = self.get_dates()
        data_x = []
        data_y = []

        for date in dates:
            subset = trades.filter(date_of_price__date=date)
            prices_for_day = subset.aggregate(Avg('price'))
            if prices_for_day['price__avg'] > 0:
                data_x.append(date.strftime('%Y-%m-%d'))
                data_y.append(prices_for_day['price__avg'])
        return data_x, data_y

    def get_context_data(self, **kwargs):
        context = super(GraphView, self).get_context_data(**kwargs)
        x_axis_date = []
        y_axis_price = []
        bubble_text = []
        for trade in self.get_queryset():
            x_axis_date.append(trade[2].date().strftime('%Y-%m-%d'))
            y_axis_price.append(int(trade[1]))
            desc = "#%s" % (trade[0])
            bubble_text.append(str(desc.encode('ascii', 'ignore')))

        trend_data_x, trend_data_y = self.trend_line()

        try:
            x_axis_date_start = x_axis_date[0]
        except IndexError:
            x_axis_date_start = None

        try:
            x_axis_date_end = x_axis_date[-1]
        except IndexError:
            x_axis_date_end = None

        context.update({
            "x_axis_date": x_axis_date,
            "x_axis_date_start": x_axis_date_start,
            "x_axis_date_end": x_axis_date_end,
            "y_axis_price": y_axis_price,
            "bubble_text": bubble_text,
            "trend_data_x": trend_data_x,
            "trend_data_y": trend_data_y,
        })
        return context


 class ReferenceDetailView(StaffuserRequiredMixin, SetHeadlineMixin, GraphView):
        headline = "Variation Detail"
        template_name = "ref_trades/reference_detail.html"

        def get_reference_model(self):
            return get_object_or_404(ReferenceModel, pk=self.kwargs["pk"])

        def get_headline(self):
            return "%s" % self.get_reference_model()

        def get_queryset(self):
            return TradeModel.objects.filter(
                date_of_price__gte=datetime.now() - timedelta(days=365),
                reference_model__id=self.kwargs["pk"]
            ).exclude(price=0).values_list('id', 'price' , 'date_of_price', 'title')
谢谢


谢谢你的帮助

您可以检索按日期排序的所有对象,然后使用将其拆分为日期,而不是每天执行查询

def data_points(self):
    trades = self.get_queryset()
    data_x = []
    data_y = []

    for date, subset in itertools.groupby(trades, lambda t: t.date):
        average_price = average(subset) # average() needs to be implemented
        if average_price > 0:
            data_x.append(date.strftime('%Y-%m-%d'))
            data_y.append(average_price)
    return data_x, data_y 

这种方法将web服务器CPU换成DB CPU/IO,这可能是最好的方法,也可能不是最好的方法,具体取决于您的基础设施

您是否使用缓存?不在本地进行开发当DDT更可能遇到这个问题时,您可能希望至少为dev打开
LocMemCache
。唯一的问题是
data\u points
中for循环中的查询。感谢Iain,groupby帮了大忙。结果:22毫秒内查询5次!再次感谢,非常感谢!