Русский
Русский
English
Статистика
Реклама

Перевод Быстрый и грязный Django Передача данных в JavaScript без AJAX

Привет, хабровчане. Для будущих студентов курса "Web-разработчик на Python" подготовили перевод материала.


Если мы хотим передать данные из Django в JavaScript, мы обычно говорим об API, сериализаторах, вызовах JSON и AJAX. Обычно дело усложняется наличием React или Angular на фронте.

Но иногда вам нужно сделать что-то быстро и грязное построить диаграмму и не задумываться над инфраструктурой одностраничного приложения.

Обычный подход

Допустим, у нас есть приложение на Django со следующей моделью:

from django.db import modelsclass SomeDataModel(models.Model):    date = models.DateField(db_index=True)    value = models.IntegerField()

И простой TemplateView:

<img alt="Изображение выглядит как текст

from django.views.generic import TemplateViewclass SomeTemplateView(TemplateView):    template_name = 'some_template.html'

Теперь мы можем построить простую линейную диаграмму с помощью Chart.js, и мы не хотим использовать AJAX, создавать новые API и т.д.

Если мы хотим визуализировать простую линейную диаграмму в нашем some_template.html, код будет выглядеть следующим образом (взято из этих примеров):

<canvas id="chart"></canvas><script src="http://personeltest.ru/aways/cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js"></script><script>window.onload = function () {  var data = [48, -63, 81, 11, 70];  var labels = ['January', 'February', 'March', 'April', 'May'];  var config = {    type: 'line',    data: {      labels: labels,      datasets: [        {          label: 'A random dataset',          backgroundColor: 'black',          borderColor: 'lightblue',          data: data,          fill: false        }      ]    },    options: {      responsive: true    }  };  var ctx = document.getElementById('chart').getContext('2d');  window.myLine = new Chart(ctx, config);};</script>

И получится следующее:

Теперь, если мы захотим построить диаграмму данных, поступающих из SomeDataModel, мы подойдем к этой задаче следующим образом:

from django.views.generic import TemplateViewfrom some_project.some_app.models import SomeDataModelclass SomeTemplateView(TemplateView):    template_name = 'some_template.html'    def get_context_data(self, **kwargs):        context = super().get_context_data(**kwargs)        context['data'] = [            {                'id': obj.id,                'value': obj.value,                'date': obj.date.isoformat()            }            for obj in SomeDataModel.objects.all()        ]        return context

А затем мы визуализируем массив JavaScript с помощью шаблона Django:

<canvas id="chart"></canvas><script src="http://personeltest.ru/aways/cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js"></script><script>window.onload = function () {  // We render via Django template  var data = [    {% for item in data %}      {{ item.value }},    {% endfor %}  ]  // We render via Django template  var labels = [    {% for item in data %}      "{{ item.date }}",    {% endfor %}  ]  console.log(data);  console.log(labels);  var config = {    type: 'line',    data: {      labels: labels,      datasets: [        {          label: 'A random dataset',          backgroundColor: 'black',          borderColor: 'lightblue',          data: data,          fill: false        }      ]    },    options: {      responsive: true    }  };  var ctx = document.getElementById('chart').getContext('2d');  window.myLine = new Chart(ctx, config);};</script>

Именно так это и работает, но, как по мне, слишком грязно. У нас больше нет JavaScript, но есть JavaScript с шаблоном Django. Мы теряем возможность выделить JavaScript в отдельный файл .js. Также мы не можем красиво работать с этим JavaScript.

Но можем сделать лучше и быстрее.

Добавим остроты

Стратегия следующая:

  1. В нашем случае мы будем сериализовать данные через json.dumps и хранить их в контексте.

  2. Отрендерим скрытый элемент <div> с уникальным id и атрибутом data-json, а именно с сериализованными данными JSON.

  3. Запросите этот <div> из JavaScript, прочитайте атрибут data-json и используйте JSON.parse, чтобы получить необходимые данные.

Преимуществом становится то, что код на JavaScript не содержит шаблонов Django, но имеет переиспользуемый шаблон для получения необходимых данных.

Почти как упрощенный AJAX.

Ниже пример того, как я использую эту стратегию:

import jsonfrom django.views.generic import TemplateViewclass SomeTemplateView(TemplateView):    template_name = 'some_template.html'    def get_context_data(self, **kwargs):        context = super().get_context_data(**kwargs)        context['data'] = json.dumps(            [                {                    'id': obj.id,                    'value': obj.value,                    'date': obj.date.isoformat()                }                for obj in SomeDataModel.objects.all()            ]        )        return context

Теперь извлечем наш код на JavaScript в статичный файл chart.js.

В результате получим some_template.html:

{% load static %}<div style="display: none" id="jsonData" data-json="{{ data }}"></div><canvas id="chart"></canvas><script src="http://personeltest.ru/aways/cdn.jsdelivr.net/npm/chart.js@2.9.4/dist/Chart.min.js"></script><script src="{% static 'chart.js' %}"></script>

Как видите в скрытом div происходит магия. Мы скрываем div, чтобы удалить его из любой верстки. Здесь вы можете дать ему соответствующий id или использовать любой подходящий HTML-элемент.

Атрибут data-json (который необязателен и не является чем-то предопределенным) содержит нужный нам JSON.

Теперь, наконец, мы реализуем следующую простую функцию для получения и анализа необходимых нам данных:

function loadJson(selector) {  return JSON.parse(document.querySelector(selector).getAttribute('data-json'));}

И вот наш chart.js готов:

function loadJson(selector) {  return JSON.parse(document.querySelector(selector).getAttribute('data-json'));}window.onload = function () {  var jsonData = loadJson('#jsonData');  var data = jsonData.map((item) => item.value);  var labels = jsonData.map((item) => item.date);  console.log(data);  console.log(labels);  var config = {    type: 'line',    data: {      labels: labels,      datasets: [        {          label: 'A random dataset',          backgroundColor: 'black',          borderColor: 'lightblue',          data: data,          fill: false        }      ]    },    options: {      responsive: true    }  };  var ctx = document.getElementById('chart').getContext('2d');  window.myLine = new Chart(ctx, config);};

Быстрый и грязный способ для тех, кто просто хочет что-то отправить. А вот и конечный результат:

Дисклеймер

Я не рекомендую вам пользоваться этим подходом для чего-то большего, чем грязное доказательство концепции. Как только ваш код на JavaScript начнет расти, станет сложно его контролировать. Рекомендуется пройти путь SPA с одним из популярных фреймворков (в нашем случае React).


Узнать подробнее о курсе "Web-разработчик на Python".

Посетить Demo day к курсу.

Источник: habr.com
К списку статей
Опубликовано: 18.03.2021 16:05:16
0

Сейчас читают

Комментариев (0)
Имя
Электронная почта

Блог компании otus

Python

Django

Веб-разработка

Категории

Последние комментарии

  • Имя: Макс
    24.08.2022 | 11:28
    Я разраб в IT компании, работаю на арбитражную команду. Мы работаем с приламы и сайтами, при работе замечаются постоянные баны и лаги. Пацаны посоветовали сервис по анализу исходного кода,https://app Подробнее..
  • Имя: 9055410337
    20.08.2022 | 17:41
    поможем пишите в телеграм Подробнее..
  • Имя: sabbat
    17.08.2022 | 20:42
    Охренеть.. это просто шикарная статья, феноменально круто. Большое спасибо за разбор! Надеюсь как-нибудь с тобой связаться для обсуждений чего-либо) Подробнее..
  • Имя: Мария
    09.08.2022 | 14:44
    Добрый день. Если обладаете такой информацией, то подскажите, пожалуйста, где можно найти много-много материала по Yggdrasil и его уязвимостях для написания диплома? Благодарю. Подробнее..
© 2006-2024, personeltest.ru