Comment créer un tableau de bord analytique dans une application Django

Salut les gens!

Python , la visualisation de données et la programmation sont les sujets auxquels je me consacre profondément. C'est pourquoi j'aimerais partager avec vous mes idées ainsi que mon enthousiasme à découvrir de nouvelles façons de présenter les données de manière significative.

Le cas que je vais aborder est assez courant: vous avez des données sur le back-end de votre application et souhaitez lui donner une forme sur le front-end. Si une telle situation vous semble familière, ce didacticiel peut vous être utile.

Une fois terminé, vous aurez une application alimentée par Django avec des tableaux croisés dynamiques et des graphiques interactifs .

Conditions préalables

Pour parcourir les étapes en toute confiance, vous avez besoin d'une connaissance de base du framework Django et d' un peu de créativité . ✨

Pour suivre, vous pouvez télécharger l'exemple GitHub.

Voici une brève liste des outils que nous allons utiliser:

  • Python 3.7.4
  • Django
  • Virtualenv
  • Tableau croisé dynamique et graphiques Flexmonster (bibliothèque JavaScript)
  • SQLite

Si vous avez déjà configuré un projet Django et que vous êtes confiant dans le flux de base de la création d'applications, vous pouvez passer directement à la section Connexion des données à Flexmonster qui explique comment y ajouter des composants de visualisation de données.

Commençons!

Premiers pas avec Django

Tout d'abord, assurons-nous d'avoir installé Django sur votre machine. La règle de base est de l'installer dans votre environnement virtuel précédemment configuré - un outil puissant pour isoler vos projets les uns des autres.

Assurez-vous également que vous avez activé dans un répertoire nouvellement créé. Ouvrez votre console et démarrez un projet Django avec cette commande:

django-admin startproject analytics_project

Il y a maintenant un nouveau répertoire appelé analytics_project. Vérifions si nous avons tout fait correctement. Accédez au analytics_projectserveur et démarrez-le avec une commande de console:

python manage.py runserver

Ouvrez //127.0.0.1:8000/dans votre navigateur. Si vous voyez cette formidable fusée, alors tout va bien:

Ensuite, créez une nouvelle application dans votre projet. Appelons-le dashboard:

python manage.py startapp dashboard

Voici une astuce : si vous n'êtes pas sûr de la différence entre les concepts d'applications et de projets dans Django, prenez le temps de vous renseigner à ce sujet pour avoir une image claire de l'organisation des projets Django.

Et c'est parti. Nous voyons maintenant un nouveau répertoire dans le projet. Il contient les fichiers suivants:

__init__.py pour que Python le traite comme un package

admin.py - paramètres des pages d'administration de Django

apps.py - paramètres pour les configurations de l'application

models.py - classes qui seront converties en tables de base de données par l'ORM de Django

tests.py - cours de test

views.py - fonctions et classes qui définissent la manière dont les données sont affichées dans les modèles

Ensuite, il est nécessaire d'enregistrer l'application dans le projet.

Accédez à analytics_project/settings.pyet ajoutez le nom de l'application à la INSTALLED_APPSliste:

INSTALLED_APPS = [ 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', 'dashboard', ]

Maintenant, notre projet est conscient de l'existence de l'application.

Vues

Dans le dashboard/views.py, nous allons créer une fonction qui dirige un utilisateur vers les modèles spécifiques définis dans le dashboard/templatesdossier. Les vues peuvent également contenir des classes.

Voici comment nous le définissons:

from django.http import JsonResponse from django.shortcuts import render from dashboard.models import Order from django.core import serializers def dashboard_with_pivot(request): return render(request, 'dashboard_with_pivot.html', {})

Une fois appelée, cette fonction sera rendue dashboard_with_pivot.html- un modèle que nous définirons bientôt. Il contiendra les composants du tableau croisé dynamique et des graphiques croisés dynamiques.

Encore quelques mots sur cette fonction. Son requestargument, une instance de HttpRequestObject, contient des informations sur la requête, par exemple la méthode HTTP utilisée (GET ou POST). La méthode renderrecherche les modèles HTML dans un templatesrépertoire situé dans le répertoire de l'application.

Nous devons également créer une méthode auxiliaire qui envoie la réponse avec des données au tableau croisé dynamique sur le front-end de l'application. Appelons ça pivot_data:

def pivot_data(request): dataset = Order.objects.all() data = serializers.serialize('json', dataset) return JsonResponse(data, safe=False)

Probablement, votre IDE vous dit qu'il ne trouve pas de référence Orderdans models.py. Pas de problème - nous y reviendrons plus tard.

Modèles

Pour l'instant, nous allons profiter du système de template Django.

Créons un nouveau répertoire à l' templatesintérieur dashboardet créons le premier modèle HTML appelé dashboard_with_pivot.html. Il sera affiché à l'utilisateur sur demande. Ici, nous ajoutons également les scripts et les conteneurs pour les composants de visualisation de données:

  Dashboard with Flexmonster 

Mappage des fonctions de vues aux URL

Pour appeler les vues et afficher les modèles HTML rendus à l'utilisateur, nous devons mapper les vues aux URL correspondantes.

Voici un conseil: l'un des principes de conception d'URL de Django dit à propos du couplage lâche, nous ne devrions pas créer d'URL avec les mêmes noms que les fonctions Python.

Go to analytics_app/urls.py and add relevant configurations for the dashboard app at the project's level.

from django.contrib import admin from django.urls import path, include urlpatterns = [ path('admin/', admin.site.urls), path('dashboard/', include('dashboard.urls')), ] 

Now the URLs from the dashboard app can be accessed but only if they are prefixed by dashboard.

After, go to dashboard/urls.py (create this file if it doesn’t exist) and add a list of URL patterns that are mapped to the view functions:

from django.urls import path from . import views urlpatterns = [ path('', views.dashboard_with_pivot, name="dashboard_with_pivot"), path('data', views.pivot_data, name="pivot_data"), ]

Model

And, at last, we've gotten to data modeling. This is my favorite part.

As you might know, a data model is a conceptual representation of the data stored in a database.

Since the purpose of this tutorial is to show how to build interactive data visualization inside the app, we won’t be worrying much about the database choice. We’ll be using SQLite - a lightweight database that ships with the Django web development server.

But keep in mind that this database is not the appropriate choice for production development. With the Django ORM, you can use other databases that use the SQL language, such as PostgreSQL or MySQL.

For the sake of simplicity, our model will consist of one class. You can create more classes and define relationships between them, complex or simple ones.

Imagine we're designing a dashboard for the sales department. So, let's create an Order class and define its attributes in dashboard/models.py:

from django.db import models class Order(models.Model): product_category = models.CharField(max_length=20) payment_method = models.CharField(max_length=50) shipping_cost = models.CharField(max_length=50) unit_price = models.DecimalField(max_digits=5, decimal_places=2)

Working with a database

Now we need to create a database and populate it with records.

But how can we translate our model class into a database table?

This is where the concept of migration comes in handy. Migration is simply a file that describes which changes must be applied to the database. Every time we need to create a database based on the model described by Python classes, we use migration.

The data may come as Python objects, dictionaries, or lists. This time we'll represent the entities from the database using Python classes that are located in the models directory.

Create migration for the app with one command:

python manage.py makemigrations dashboard

Here we specified that the app should tell Django to apply migrations for the dashboard app's models.

After creating a migration file, apply migrations described in it and create a database:

python manage.py migrate dashboard

If you see a new file db.sqlite3 in the project's directory, we are ready to work with the database.

Let's create instances of our Order class. For this, we'll use the Django shell - it's similar to the Python shell but allows accessing the database and creating new entries.

So, start the Django shell:

python manage.py shell

And write the following code in the interactive console:

from dashboard.models import Order >>> o1 = Order( ... product_category="Books", ... payment_method="Credit Card", ... shipping_cost=39, ... unit_price=59 ... ) >>> o1.save()

Similarly, you can create and save as many objects as you need.

Connecting data to Flexmonster

And here's what I promised to explain.

Let's figure out how to pass the data from your model to the data visualization tool on the front end.

To make the back end and Flexmonster communicate, we can follow two different approaches:

  • Using the request-response cycle. We can use Python and the Django template engine to write JavaScript code directly in the template.
  • Using an async request (AJAX) that returns the data in JSON.

In my mind, the second one is the most convenient because of a number of reasons. First of all, Flexmonster understands JSON. To be precise, it can accept an array of JSON objects as input data. Another benefit of using async requests is the better page loading speed and more maintainable code.

Let's see how it works.

Go to the templates/dashboard_pivot.html.

Here we've created two div containers where the pivot grid and pivot charts will be rendered.

Within the ajax call, we make a request based on the URL contained in the data-URL property. Then we tell the ajax request that we expect a JSON object to be returned (defined by dataType).

Once the request is completed, the JSON response returned by our server is set to the data parameter, and the pivot table, filled with this data, is rendered.

The query result (the instance of JSONResponse) returns a string that contains an array object with extra meta information, so we should add a tiny function for data processing on the front end. It will extract only those nested objects we need and put them into a single array. This is because Flexmonster accepts an array of JSON objects without nested levels.

function processData(dataset) { var result = [] dataset = JSON.parse(dataset); dataset.forEach(item => result.push(item.fields)); return result; }

After processing the data, the component receives it in the right format and performs all the hard work of data visualization. A huge plus is that there’s no need to group or aggregate the values of objects manually.

Here's how the entire script in the template looks:

function processData(dataset) { var result = [] dataset = JSON.parse(dataset); dataset.forEach(item => result.push(item.fields)); return result; } $.ajax({ url: $("#pivot-table-container").attr("data-url"), dataType: 'json', success: function(data) { new Flexmonster({ container: "#pivot-table-container", componentFolder: "//cdn.flexmonster.com/", width: "100%", height: 430, toolbar: true, report: { dataSource: { type: "json", data: processData(data) }, slice: {} } }); new Flexmonster({ container: "#pivot-chart-container", componentFolder: "//cdn.flexmonster.com/", width: "100%", height: 430, //toolbar: true, report: { dataSource: { type: "json", data: processData(data) }, slice: {}, "options": { "viewType": "charts", "chart": { "type": "pie" } } } }); } });

Don't forget to enclose this JavaScript code in tags.

Phew! We’re nearly there with this app.

Fields customization

Flexmonster provides a special property of the data source that allows setting field data types, custom captions, and defining multi-level hierarchies.

This is a nice feature to have - we can elegantly separate data and its presentation right in the report's configuration.

Add it to the dataSource property of the report:

mapping: { "product_category": { "caption": "Product Category", "type": "string" }, "payment_method": { "caption": "Payment Method", "type": "string" }, "shipping_cost": { "caption": "Shipping Cost", "type": "number" }, "unit_price": { "caption": "Unit Price", "type": "number" } }

Dashboard's design

To make the dashboard, we’ve rendered two instances of Flexmonster (you can create as many as you want, depending on the data visualization goals you want to reach). One is for the pivot table with summarized data, and the other is for the pivot charts.

Both instances share the same data source from our model. I encourage you to try making them work in sync: with the reportchange event, you can make one instance react to the changes in another one.

You can also redefine the ‘Export’ button’s functionality on the Toolbar to make it save your reports to the server.

Results

Let’s start the Django development server and open //127.0.0.1:8000/dashboard/ to see the resulting dashboard:

Looks nice, doesn't it?

Feedback

This time we learned how to create a simple Django app and display the data on the client side in the form of an analytics dashboard.

I do hope you enjoyed the tutorial!

Please leave your comments below - any feedback on the code’s improvement is highly appreciated.

References

The source code for the tutorial can be found on GitHub.

And here’s the project with Flexmonster & Django integration that inspired me for this tutorial.

Further, I recommend walking through important concepts in the documentation to master Django:

  • Migrations in Django
  • QuerySets
  • Serializing Django objects