Рубрики
Без рубрики

Добавление диаграмм в Django Admin

Введение Django предлагает функциональный администратор UI из коробки с помощью Crud Interface для DB … Tagged с Django, Charts, JavaScript, Python.

Вступление

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

К счастью, приложение администратора Django расширяется и с несколькими настройками мы можем добавить интерактивные диаграммы JavaScript для администратора.

Проблема

Я хотел получить обзор графика абонентов по электронной почте со временем на Findwork.dev Отказ Растет сайт или застой с точки зрения абонентов электронной почты? Сколько подписчиков у нас было прошло месяц? На какой неделе мы получили большинство подписчиков? Все ли подписчики подтверждают свои письма?

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

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

Вот когда идея возникла на ум: Почему не расширить приложение по умолчанию?

Удлинение Django-Admin

Приложение администратора Django состоит ModelAdmin Classes Отказ Они представляют визуальный вид вашей модели в интерфейсе администратора. По умолчанию класс ModelAdmin поставляется с 5 представлениями по умолчанию:

  • Changelist – вид списка коллекции модели
  • Добавить – вид, который позволяет добавить новый экземпляр модели
  • Изменить – вид для обновления экземпляра модели
  • Удалить – вид для подтверждения удаления экземпляра модели
  • История – история действий, предпринятых на экземпляре модели

Просмотр Changelist – это представление администратора по умолчанию, когда вы хотите увидеть конкретную модель. Я хотел добавить диаграмму здесь, так что в любое время я открываю страницу EmailSubsCribers, мне было бы представить с добавленными подписчиками со временем.

Предположим, у нас есть модель абонентов по электронной почте, как так:

# web/models.py
from django.db import models

class EmailSubscriber(models.Model):
    email = models.EmailField()
    created_at = models.DateTimeField()

Чтобы представить абоненты электронной почты в приложении администратора, нам нужно создать класс, который простирается от django.contrib.admin. ModelAdmin. .

Основной ModelAdmin будет выглядеть что-то подобное:

# web/admin.py
from django.contrib import admin
from .models import EmailSubscriber

@admin.register(EmailSubscriber)
class EmailSubscriberAdmin(admin.ModelAdmin):
    list_display = ("id", "email", "created_at") # display these table columns in the list view
    ordering = ("-created_at",)                  # sort by most recent subscriber

Давайте добавим некоторые подписчики, чтобы у нас был начальный набор данных:

$ ./manage.py shell
Python 3.7.3 (default, Apr  9 2019, 04:56:51)
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
(InteractiveConsole)
from web.models import EmailSubscriber
from django.utils import timezone
from datetime import timedelta
import random
for i in range(0, 100):
    EmailSubscriber.objects.create(email=f"user_{i}@email.com", created_at=timezone.now() - timedelta(days=random.randint(0, 100)))
...



...

Если мы введем представление Changelist, мы увидим, что мы добавили 100 новых подписчиков со случайным временем создания http://localhost: 8000/admin/web/eailsubscriber/ Отказ

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

Красная область ниже очерчиков, где я хочу поставить график визуально.

Если мы создадим новый файл, мы можем заставить Django-admin загрузить наш шаблон вместо этого шаблона по умолчанию. Давайте создадим пустой файл в

  • Веб/шаблоны/admin/web/eailsubscriber/formit_list.html Отказ

Схема именования при переопределении шаблонов администратора

  • {{app}}/шаблоны/admin/{{app}}/{{model}}/formit_list.html Отказ

Вид Changelist по умолчанию расширяется и имеет несколько блоков, которые могут быть переопределены в соответствии с вашими потребностями. При проверке Шаблон администратора по умолчанию Мы можем видеть, что он содержит блоки, которые могут быть переопределены. Нам нужно переопределить Содержание Блок, чтобы изменить то, что визуализируется до моделей таблицы.

Давайте продлим представление Changelist по умолчанию и добавить пользовательский текст:

# web/templates/admin/web/emailsubscriber/change_list.html

{% extends "admin/change_list.html" %}
{% load static %}
{% block content %}

Custom message!

{{ block.super }} {% endblock %}

Cool, мы теперь удавали настроить Admin UI. Пойдем дальше и добавьте диаграмму JavaScript, используя Chart.js Отказ Нам нужно переопределить Extrahead Блок, чтобы добавить скрипт и элементы стиля для загрузки Chart.js в заголовке.

Код Chart.js основан на их демонстрационной диаграмме найден здесь Отказ Я немного изменил его, чтобы прочитать данные серии Time на оси X.

# web/templates/admin/web/emailsubscriber/change_list.html

{% extends "admin/change_list.html" %}
{% load static %}


{% block extrahead %}
{{ block.super }}



{% endblock %}

{% block content %}

{{ block.super }} {% endblock %}

Вуаля, мы теперь представили диаграмму Chart.js в админ Django. Единственная проблема заключается в том, что данные заканчиваются и не получены из нашей бэкенда.

Инъекционные данные диаграммы в шаблон администратора

У класса ModelAdmin есть метод под названием ChangeList_View Отказ Этот метод отвечает за рендеринг страницы Changelist. Переопределяя этот метод, мы сможем вводить данные диаграммы в контекст шаблона.

Код ниже примерно делает это:

  1. Агрегаты общее количество новых подписчиков на ежедневном интервале
  2. кодирует запрос Django к JSON
  3. Добавляет данные в контекст шаблона
  4. Вызывает метод Super () для визуализации страницы
# django_admin_chart_js/web/admin.py
import json

from django.contrib import admin
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Count
from django.db.models.functions import TruncDay

from .models import EmailSubscriber


@admin.register(EmailSubscriber)
class EmailSubscriberAdmin(admin.ModelAdmin):
    list_display = ("id", "email", "created_at")
    ordering = ("-created_at",)

    def changelist_view(self, request, extra_context=None):
        # Aggregate new subscribers per day
        chart_data = (
            EmailSubscriber.objects.annotate(date=TruncDay("created_at"))
            .values("date")
            .annotate(y=Count("id"))
            .order_by("-date")
        )

        # Serialize and attach the chart data to the template context
        as_json = json.dumps(list(chart_data), cls=DjangoJSONEncoder)
        extra_context = extra_context or {"chart_data": as_json}

        # Call the superclass changelist_view to render the page
        return super().changelist_view(request, extra_context=extra_context)

Теперь данные должны быть технически добавлены в контекст шаблона, но теперь мы должны использовать его в нашем графике вместо жесткозедированных данных.

Замените жесткодируемые данные в ChartData Переменная с данными с нашей бэкэнда:

// django_admin_chart_js/web/templates/admin/web/emailsubscriber/change_list.html
const chartData = {{ chart_data | safe }};

Перезагрузить страницу, чтобы увидеть наш красивый график.

Динамически загрузка данных с использованием JS

В приведенном выше примере мы вводим данные начальных диаграмм непосредственно в шаблон HTML. Мы могли бы более интерактивные и получать данные после нагрузки на начальную страницу. Для этого нам нужно:

  • Добавьте новую конечную точку нашу модель Admin, которая возвращает данные JSON
  • Добавьте логику JS, чтобы сделать вызовы ajax на кнопку щелкните и перезагрузите диаграмму

Добавление новой конечной точки требует, чтобы мы переопределили get_urls () Метод над ModelAdmin и ввести нашу собственную конечную точку URL.

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

Наш код Python теперь должен выглядеть что-то подобное:

# web/admin.py
import json

from django.contrib import admin
from django.core.serializers.json import DjangoJSONEncoder
from django.db.models import Count
from django.db.models.functions import TruncDay
from django.http import JsonResponse
from django.urls import path

from .models import EmailSubscriber

@admin.register(EmailSubscriber)
class EmailSubscriberAdmin(admin.ModelAdmin):
    list_display = ("id", "email", "created_at")
    ordering = ("-created_at",)

    ...

    def get_urls(self):
        urls = super().get_urls()
        extra_urls = [
            path("chart_data/", self.admin_site.admin_view(self.chart_data_endpoint))
        ]
        # NOTE! Our custom urls have to go before the default urls, because they
        # default ones match anything.
        return extra_urls + urls

    # JSON endpoint for generating chart data that is used for dynamic loading
    # via JS.
    def chart_data_endpoint(self, request):
        chart_data = self.chart_data()
        return JsonResponse(list(chart_data), safe=False)

    def chart_data(self):
        return (
            EmailSubscriber.objects.annotate(date=TruncDay("created_at"))
            .values("date")
            .annotate(y=Count("id"))
            .order_by("-date")
        )

Нам также необходимо добавить логику JavaScript, чтобы перезагрузить данные диаграммы на кнопку щелкнуть и перенести диаграмму. Добавьте следующие строки под объявлением переменной диаграммы:

  // django_admin_chart_js/web/templates/admin/web/emailsubscriber/change_list.html

  const chart = new Chart...
  ...

  // Reload chart data from the backend on button click
  const btn = document.querySelector('#reload');
  btn.addEventListener('click', async() => {
    const res = await fetch("/admin/web/emailsubscriber/chart_data/");
    const json = await res.json();
    json.forEach((d) => {
      d.x = new Date(d.date);
    });
    chart.data.datasets[0].data = json;
    chart.update();
  });

Добавить кнопку HTML ниже в диаграмму:

{% block content %}

{{ block.super }} {% endblock %}

Chart.js поставляется с различными визуализациями из коробки. Легко попасть с базовыми диаграммами и предлагает настройку на случай, если вам это нужно.

Docks chart.js – здесь и Django Admin Docs здесь Отказ

Полный пример код можно найти на Github Отказ

Оригинал: “https://dev.to/danihodovic/integrating-chart-js-with-django-admin-1kjb”