如何将大量参数传递给Django中的视图?

时间:2010-04-27 00:00:03

标签: python django parameters charts

我是Django的新手,我正在尝试构建一个应用程序来在表格和图表中显示我的数据。直到现在我的学习过程非常顺利,但现在我有点卡住了。

我的网页浏览从数据库中检索大量数据并将其放入上下文中。然后模板生成不同的html表。到目前为止一切顺利。
现在我想为模板添加不同的图表。我设法通过定义<img src=".../> tags.来实现这一点。在我的chartview中生成Matplotlib图表并返回通过:

response=HttpResponse(content_type='image/png')
canvas.print_png(response)
return response

现在我有不同的问题:

  1. 从数据库中检索两次数据。一旦进入页面视图以呈现表格,再次在图表视图中进行制作图表。将页面上下文中的数据传递给chartview的最佳方法是什么?
  2. 我需要很多图表,每个图表都有不同的数据集。我可以为每个图表制作一个图表视图,但可能有更好的方法。如何将不同的数据集名称传递给chartview?有些图表有20个数据集,所以我不认为通过网址传递这些数据集参数(如:<imgm src="chart/dataset1/dataset2/.../dataset20/chart.png />)是正确的方法。
    有什么建议吗?

2 个答案:

答案 0 :(得分:6)

您无法将数据从页面视图传递到图表视图,因为它们是单独的HTTP请求。您有几个选择:

  1. 传递图表网址中的所有数据。这可能听起来很疯狂,但这正是谷歌图表的作用:http://code.google.com/apis/chart/docs/making_charts.html

  2. 将数据存储在会话中。页面视图将填充会话中的数据,图表视图将使用它来创建图表。

  3. 在memcache中缓存数据库查询。由于页面和图表都将引用相同的查询,因此您可能会访问缓存。这是一个很好的解决方案,因为即使没有首先渲染页面,您的图表仍然可以工作。

  4. 再次查询数据库。您的DBMS可能具有良好的缓存,性能可能不是您想象的问题。

  5. 对于您的第二个问题,网址中的20个字似乎不是什么大问题。当然,您可能会为所选的数据集找到一些模式,这样您就不需要每次都指定它们,但如果需要,只需制作长URL。

答案 1 :(得分:1)

使用模板标签可能就是我在这里采用的路线。我有类似的情况,我在同一页面上以不同的格式多次呈现日历信息。我处理它的方法是将查询的数据传递到请求上下文,然后简单地使用该查询集作为模板标记的参数。结果是你可以得到这样的模板语法:

查看

def my_view(request, *args, **kwargs):
    yearly_sales_qs = SaleRecord.objects.filter(param=value)
    monthly_sales_qs = SalesRecord.objects.filter(param=foo)

    return render_to_response( ..., locals(), ... )

<强>模板

{% load data_tags %}

<div class="year">
    {% render_data_table for yearly_sales_qs %}
    {% render_bar_chart for yearly_sales_qs %}
</div>

<div class="month">
    {% render_data_table for monthly_sales_qs %}
    {% render_bar_chart for monthly_sales_qs %}
</div>

那么你怎么做那样的东西?首先查看Custom template tags and filters上的Django文档。比Django的其他部分更难开始,但是一旦你得到它,它就很容易了。

  • 首先在应用的文件夹中创建一个“templatetags”文件夹。
  • 在该新文件夹
  • 中创建一个空白文件“ init .py”
  • 将该templatetags文件夹的位置添加到TEMPLATE_DIRS中的settings.py设置中(如果它尚未存在)

因为我们将制作其中的几个,我们可以制作一个我们将继承的基本模板标签,它封装了我们的基本功能......

data_tags.py (存储在templatetags文件夹中)

class DataForTag(tempalte.Node):
    @classmethod
    def handle_token(cls, parser, token, template):
        tokens = token.contents.split()
        if tokens[1] != 'for':
                raise template.TemplateSyntaxError("First argument in %r must be 'for'" % tokens[0])

        if len(tokens) == 3:
            return cls(queryset=parser.compile_filter(tokens[2]), template=template)
        else:
            raise template.TemplateSyntaxError("%r tag requires 2 arguments" % tokens[0])

    def __init__(self, queryset=None, template=None):
        self.queryset = queryset
        self.template = template

    def render(self, context):
        return render_to_string(self.template, {'queryset':self.queryset})

然后我们可以制作单独的标签来处理我们需要的任何东西......

@register.tag
def render_bar_chart(parser, token):
    return DataForTag.handle_token(parser, token, 'data/charts/barchart.html')

@register.tag
def render_pie_chart(parser, token):
    return DataForTag.handle_token(parser, token, 'data/charts/piechart.html')    

@register.tag
def render_data_table(parser, token):
    return DataForTag.handle_token(parser, token, 'data/table.html')