Как передать множество параметров представлениям в Django?

Я очень новичок в Django и пытаюсь создать приложение для представления своих данных в таблицах и диаграммах. До сих пор мой процесс обучения шел очень гладко, но теперь я немного застрял.

Мой просмотр страниц извлекает большие объемы данных из базы данных и помещает их в контекст. Затем шаблон генерирует различные html-таблицы. Пока все хорошо.
Теперь я хочу добавить в шаблон различные диаграммы. Мне удается сделать это, определив <img src=".../> tags. Диаграмма Matplotlib генерируется в моем представлении диаграммы и возвращается через:

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

Теперь у меня другие вопросы:

  1. данные извлекаются из базы данных дважды. Один раз в просмотре страницы для отображения таблиц и снова в виде диаграммы для создания диаграмм. Каков наилучший способ передать данные уже в контексте страницы в диаграмму?
  2. Мне нужно много диаграмм, каждая с разными наборами данных. Я мог бы сделать график для каждого графика, но, вероятно, есть лучший способ. Как передать разные имена наборов данных в диаграмму? Некоторые диаграммы имеют 20 наборов данных, поэтому я не думаю, что передача этих параметров набора данных через URL-адрес (например: <imgm src="chart/dataset1/dataset2/.../dataset20/chart.png />) является правильным способом.
    Есть совет?

person Mark    schedule 27.04.2010    source источник


Ответы (2)


Вы не можете передать данные из представления страницы в представление диаграммы, так как это отдельные HTTP-запросы. У вас есть несколько вариантов:

  1. Передайте все данные в URL диаграммы. Это может показаться безумием, но это именно то, что делает Google Charts: http://code.google.com/apis/chart/docs/making_charts.html

  2. Сохраните данные в сеансе. Представление страницы заполнит данные сеанса, а представление диаграммы будет использовать их для создания диаграммы.

  3. Кэшируйте запросы к БД в memcache. Поскольку и страница, и диаграмма будут ссылаться на один и тот же запрос, вы, скорее всего, попадете в кеш. Это хорошее решение, потому что ваша диаграмма будет работать даже без предварительного рендеринга страницы.

  4. Просто запросите базу данных еще раз. Ваша СУБД, вероятно, имеет хорошее кэширование, производительность может быть не такой проблемой, как вы себе представляете.

Что касается вашего второго вопроса, 20 слов в URL-адресе не кажутся такой уж большой проблемой. Конечно, вы могли бы найти какой-то шаблон для выбранных наборов данных, чтобы вам не нужно было указывать их все каждый раз, но если вам нужно, просто сделайте длинные URL-адреса.

person Ned Batchelder    schedule 27.04.2010
comment
Спасибо за ответы, Нед. № 1: это сработает, но моя интуиция подсказывает, что должно быть более «эстетичное» решение. Nr2: Это то, что я искал. Это решило проблему, которую я имею - person Mark; 28.04.2010

Использование тегов шаблона, вероятно, было бы тем путем, который я бы выбрал здесь. У меня была похожая ситуация, когда информация календаря отображалась несколько раз в разных форматах на одной странице. Я справился с этим, передав запрошенные данные в контекст запроса, а затем просто используя этот набор запросов в качестве аргумента тега шаблона. В результате вы можете получить такой синтаксис шаблона:

Просмотреть

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>

Так как же сделать что-то подобное? Начните с ознакомления с документом 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')   
person T. Stone    schedule 27.04.2010
comment
Спасибо Т. Стоун. Это, вероятно, решает мою проблему. Мне нужно сначала проверить это, чтобы быть уверенным. В любом случае, ваш ответ многому меня научил о тегах, которые будут полезны если не сейчас, то в будущем. - person Mark; 28.04.2010