html текст
All interests
  • All interests
  • Design
  • Food
  • Gadgets
  • Humor
  • News
  • Photo
  • Travel
  • Video
Click to see the next recommended page
Like it
Don't like
Add to Favorites

Mother of the gods, it is Surfingbird!

You finally got here. We've been waiting for you and we have so many interesting things!

Close

Рисуем графики (диаграммы) в Django

django-google-charts
Многие веб-разработчики время от времени сталкиваются с необходимостью визуализировать сравнительно большое количество данных при помощи диаграмм (далее я буду называть их графиками, хоть это и не совсем верно). Задача не нова, и в сети есть множество готовых решений: работающие на стороне сервера и на стороне клиента, использующие изображения, Canvas, SVG, Flash, Silverlight…

В этой статье я расскажу про django-google-charts и некоторые особенности использования Google Chart Tools для построения графиков на сайте под управлением Django.

Часто, когда нужно добавить график на страницу, разработчик идет по пути наименьшего сопротивления: копирует JavaScript из примера в интернете и как-нибудь выводит в него данные из приложения. Получается что-то наподобие:

var chart_data = [
    {% for row in chart_data %}
    [{{ row.0 }}, {{ row.1 }}],
    {% endfor %}
];

Почему это плохо?

  • Код тяжело читается, вследствие чего легко допустить ошибку. Вы же заметили ошибку в моем примере? :)
  • Сложно масштабировать. Когда нужно добавить второй график на страницу, обычно копируют этот же кусок кода еще раз и меняют имена переменных. В результате получается нечитаемая каша, отлаживать это и вносить изменения достаточно неприятно.
  • Сильное связывание с контекстом. Повторное использование такого шаблона ограничено.
Для временного решения такая конструкция еще годится, но не более.

Постановка задачи


Хорошее решение для рисования графиков:
  1. Позволяет просто и понятно добавлять новые графики на сайт и убирать ненужные;
  2. Соблюдает принцип DRY для определения общих элементов (например, цветовой схемы);
  3. Можно повторно использовать;
  4. Не изобретает нового API.

Вариант решения


Приложение для компоновки графиков django-google-charts выросло из небольшого набора хаков в моем текущем проекте. Алярма: это первый публичный релиз, возможны причудливые баги. Исправления и замечания всячески приветствуются.

Установка

$ pip install django-google-charts
# или
$ easy_install django-google-charts

Добавляем 'googlecharts' в INSTALLED_APPS.

Как это работает (общий вид)

{% load googlecharts %}

{% googlecharts %}
    {% data переменная "необязательное имя" %} {# (именованный) набор данных #}
        {% col "тип" "название" %}...{% endcol %} {# формат #}
        {% col "тип" "название" %}...{% endcol %} {# еще формат #}
        ...
    {% enddata %}

    {% options "необязательное имя" %} {# (именованный) набор опций #}
        ...
    {% endoptions %}

    {% graph "#id" "данные" "опции" %} {# точка сборки #}
{% endgooglecharts %}

Расскажу немного про назначение каждого тега.

{% googlecharts %}...{% endgooglecharts %}

Подключает необходимые скрипты, является контейнером для всей конструкции. Ничего интересного.

{% data переменная "имя" %}...{% enddata %}

Именованный набор данных. Имя можно не указывать (получится "default").

{% col "тип" "название" %}...{% endcol %}

Формат. Типы данных в Google Visualization API вот такие:

'string' 'number' 'boolean' 'date' 'datetime' 'timeofday'

Подробнее можно почитать в документации.

Внутрь тега передается специальная переменная val, в этом месте ее можно форматировать:

{% col "string" "Date" %}'{{ val|date:"M j" }}'{% endcol %}
{# или, например #}
{% col "number" %}{{ val|floatformat:2 }}{% endcol %}

Результат должен соответствовать заявленному типу; кавычки вокруг строки сами не поставятся.

Пример. Допустим, в блок {% data %} мы передали такую переменную контекста:

[['foo', 32], ['bar', 64], ['baz', 96]]

Нам нужны два тега {% col %}, по количеству элементов в строке входных данных. Первый получит на вход 'foo', 'bar' и 'baz'; второй, соответственно, 32, 64 и 96. Реализация (самая простая) может выглядеть так:

{% col "string" "Name" %}"{{ val }}"{% endcol %}
{% col "number" "Value" %}{{ val }}{% endcol %}

{% options "имя" %}...{% endoptions %}

Параметры графика.

{% options %}
    kind: "LineChart",
    options: {
        width: 300,
        height: 240
        // ...
    }
{% endoptions %}

Внутри тега объект JavaScript, можно использовать глобальные переменные и вызывать функции. Типы графиков и поддерживаемые опции для каждого типа перечислены вот здесь.

{% graph "id_элемента" "данные" "опции" %}

Выводим график в элемент на странице. Последние два параметра можно не указывать, получится "default" "default".

Пример использования


Предположим, у нас есть такая модель:

class Payment(models.Model):
    amount = models.DecimalField(max_digits=11, decimal_places=4)
    datetime = models.DateTimeField()

Для подготовки данных к отображению в виде графика можно использовать django-qsstats-magic.

from qsstats import QuerySetStats

def view_func(request):
    start_date = ...
    end_date = ...

    queryset = Payment.objects.all()
    # считаем количество платежей...
    qsstats = QuerySetStats(queryset, date_field='datetime', aggregate=Count('id'))
    # ...в день за указанный период
    values = qsstats.time_series(start_date, end_date, interval='days')

    return render_to_response('template.html', {'values': values})

Метод time_series возвращает данные в таком виде:

[[date, value], [date, value], ...]

В файле template.html:

{% load googlecharts %}

<div id="count_graph"></div>

{% googlecharts %}
	{% data values "count" %}
		{% col "string" "Date" %}"{{ val|date:"M j" }}"{% endcol %}
		{% col "number" "# of payments" %}{{ val }}{% endcol %}
	{% enddata %}

	{% options %}
		kind: "LineChart",
		options: {
			backgroundColor: "#f9f9f9",
			colors: ["#09f"],
			gridlineColor: "#ddd",
			legend: "none",
			vAxis: {minValue: 0},
			chartArea: {left: 40, top: 20, width: 240, height: 180},
			width: 300,
			height: 240
		}
	{% endoptions %}

	{% graph "count_graph" "count" %} {# используем опции по умолчанию #}
{% endgooglecharts %}

Масштабирование

Теперь, чтобы добавить еще один график на страницу, нужно сделать следующее:

– Собрать данные (views.py):

    # сумма всех платежей в день за указанный период
    summary = qsstats.time_series(start_date, end_date, interval='days', aggregate=Sum('amount'))

    return render_to_response('template.html', {'values': values, 'summary': summary})

– Добавить в template.html:

<div id="count_sum"></div>
...
{% data summary "sum" %}
	{% col "string" "Date" %}"{{ val|date:"M j" }}"{% endcol %}
	{% col "number" "Paid amount, USD" %}{{ val|floatformat:2 }}{% endcol %}
{% enddata %}
...
{% graph "count_sum" "sum" %} {# используем опции по умолчанию, снова #}

GitHub


Исходный код django-google-charts содержит также демонстрационный проект. Чтобы его запустить, достаточно выполнить:

$ python manage.py syncdb --noinput  # создает базу данных sqlite в /tmp
$ python manage.py populatedb        # наполняет ее случайными данными
$ python manage.py runserver

Выглядит тестовый проект вот так:

django-google-charts

Ограничения первого публичного релиза (ложка дегтя)

  1. Только один тег {% googlecharts %} на странице;
  2. (Почти) нет проверки ошибок, особенно в JavaScript;
  3. Исчезающе мало документации.
Спасибо всем, кто дочитал. А как вы рисуете графики?
Читать дальше
Twitter
Одноклассники
Мой Мир

материал с habrahabr.ru

85
    +67 surfers

      Add

      You can create thematic collections and keep, for instance, all recipes in one place so you will never lose them.

      No images found
      Previous Next 0 / 0
      500
      • Advertisement
      • Animals
      • Architecture
      • Art
      • Auto
      • Aviation
      • Books
      • Cartoons
      • Celebrities
      • Children
      • Culture
      • Design
      • Economics
      • Education
      • Entertainment
      • Fashion
      • Fitness
      • Food
      • Gadgets
      • Games
      • Health
      • History
      • Hobby
      • Humor
      • Interior
      • Moto
      • Movies
      • Music
      • Nature
      • News
      • Photo
      • Pictures
      • Politics
      • Psychology
      • Science
      • Society
      • Sport
      • Technology
      • Travel
      • Video
      • Weapons
      • Web
      • Work
        Submit
        Valid formats are JPG, PNG, GIF.
        Not more than 5 Мb, please.
        30
        surfingbird.ru/site/
        RSS format guidelines
        500
        • Advertisement
        • Animals
        • Architecture
        • Art
        • Auto
        • Aviation
        • Books
        • Cartoons
        • Celebrities
        • Children
        • Culture
        • Design
        • Economics
        • Education
        • Entertainment
        • Fashion
        • Fitness
        • Food
        • Gadgets
        • Games
        • Health
        • History
        • Hobby
        • Humor
        • Interior
        • Moto
        • Movies
        • Music
        • Nature
        • News
        • Photo
        • Pictures
        • Politics
        • Psychology
        • Science
        • Society
        • Sport
        • Technology
        • Travel
        • Video
        • Weapons
        • Web
        • Work

          Submit

          Thank you! Wait for moderation.

          Тебе это не нравится?

          You can block the domain, tag, user or channel, and we'll stop recommend it to you. You can always unblock them in your settings.

          • tachikoma
          • домен habrahabr.ru

          Get a link

          Спасибо, твоя жалоба принята.

          Log on to Surfingbird

          Recover
          Sign up

          or

          Welcome to Surfingbird.com!

          You'll find thousands of interesting pages, photos, and videos inside.
          Join!

          • Personal
            recommendations

          • Stash
            interesting and useful stuff

          • Anywhere,
            anytime

          Do we already know you? Login or restore the password.

          Close

          Add to collection

             

            Facebook

            Ваш профиль на рассмотрении, обновите страницу через несколько секунд

            Facebook

            К сожалению, вы не попадаете под условия акции