Développement web • Python • Radio amateur
Django : le framework web Python expliqué simplement
De la théorie à la pratique, en passant par la radio amateur — et une API concrète disponible sur django.jerko.fr.
Mais c’est quoi, Django ?
Django est un framework web écrit en Python, publié en 2005 et aujourd’hui maintenu par la Django Software Foundation. L’idée de départ était simple : permettre à des développeurs de journaux en ligne de produire des applications web complexes en un temps minimal, sans réinventer la roue à chaque projet.
Sa philosophie tient en un slogan officiel : « The web framework for perfectionists with deadlines ». En clair : un outil complet, opiniated (il a ses propres conventions) et qui embarque tout ce dont vous avez besoin dès l’installation.
Un framework, c’est quoi exactement ? Imaginez que vous construisez une maison. Vous pourriez façonner chaque brique vous-même, concevoir votre propre plomberie, inventer vos propres techniques de maçonnerie. Ou bien vous pouvez utiliser des matériaux standard, des plans éprouvés, et vous concentrer sur ce qui rend votre maison unique. Un framework web, c’est pareil : il fournit la structure, les outils et les conventions pour que vous n’ayez plus qu’à construire ce qui vous appartient.
L’architecture MTV : Model, Template, View
Django s’organise autour d’un patron d’architecture appelé MTV (Model – Template – View), cousin du MVC que vous connaissez peut-être. Voici comment ces trois briques s’articulent :
| Composant | Rôle | Analogie |
|---|---|---|
| Model | Définit la structure des données et dialogue avec la base de données | Le carnet de logs du radioamateur |
| View | Contient la logique applicative : reçoit une requête, interroge les modèles, renvoie une réponse | Le TRX qui traite le signal |
| Template | Génère le HTML final affiché à l’utilisateur | L’écran du waterfall : la représentation visuelle |
Avantages et inconvénients — le bilan honnête
Ce qui plaît
- + Batteries included : ORM, auth, admin, formulaires, sécurité CSRF — tout est intégré
- + Django REST Framework : créer une API JSON devient trivial
- + Interface d’administration auto-générée, prête à l’emploi
- + Sécurité : protection XSS, CSRF, injection SQL par défaut
- + Scalabilité : Instagram, Pinterest et Disqus tournent sur Django
- + Communauté et documentation exemplaire
Ce qui grince
- – Courbe d’apprentissage : la magie des conventions peut être déstabilisante au début
- – Monolithique : moins agile que Flask ou FastAPI pour un micro-service minimaliste
- – Synchrone par nature : l’async existe depuis Django 3.1 mais reste moins mature qu’avec FastAPI
- – ORM parfois rigide pour des requêtes SQL très complexes ou non-standard
- – Déploiement : requiert Python + WSGI/ASGI + serveur (Gunicorn, Nginx), moins clé-en-main qu’un hébergement mutualisé PHP
Django dans le monde de la radio amateur
A priori, un framework web Python et la radio amateur semblent éloignés. Mais à y réfléchir, notre activité produit des données en abondance : logs de trafic, spots DX, trames APRS, relevés WSPR, informations de porteurs… autant de sources qui se prêtent à une mise en valeur sur le web — et Django est parfaitement outillé pour ça.
Voici quelques cas d’usage concrets pour les radioamateurs :
Logbook en ligne
Stocker, rechercher et afficher vos QSO avec filtres par bande, mode ou DXCC. L’ORM Django rend les requêtes complexes lisibles et maintenables.
DX Cluster Web
Exposer les spots d’un cluster DXSpider via une API REST, consommable par n’importe quelle interface web ou application mobile.
Statistiques WSPR / FT8
Ingérer les données de propagation (wsprnet, PSKReporter), les agréger et les restituer sous forme de tableaux ou de cartes interactives.
Gestion d’association
Adhérents, cotisations, résultats de concours, partiels de diplômes — Django propose un back-office prêt à l’emploi sans une ligne de code d’interface admin.
Carte des relais / balises
Modéliser les relais (fréquence, ton CTCSS, locator, statut) et les exposer via une API GeoJSON consommée par Leaflet.js côté navigateur.
Examen radioamateur
Banque de questions, tirage aléatoire, correction et score — une application d’entraînement complète en quelques dizaines de lignes Python. Exemple concret : django.jerko.fr/quiz/
Django vs PHP pour un radioamateur ? Si vous connaissez déjà PHP/WordPress, la transition demande un investissement initial. Mais dès que vous devez traiter des données structurées en volume — logs ADIF, trames JSON d’un SDR, exports WSPR — Python et Django s’avèrent nettement plus confortables : la syntaxe est plus lisible, les bibliothèques scientifiques (NumPy, Pandas) sont disponibles, et l’ORM évite les jointures SQL manuelles.
L’interactivité via les API REST
L’un des usages les plus puissants de Django aujourd’hui n’est plus de générer des pages HTML côté serveur, mais d’exposer des API REST — des points d’entrée web qui renvoient du JSON. N’importe quel client peut alors les interroger : un navigateur, une application mobile, un script Python, un widget WordPress…
Le module Django REST Framework (DRF) est le standard de fait pour construire ces API. Il prend en charge la sérialisation des données, l’authentification, les permissions, la pagination et même une interface de navigation interactive (la Browsable API).
Exemple : requête curl sur l’API de django.jerko.fr
# Récupérer les articles du blog via l'API REST curl -s https://django.jerko.fr/api/articles/ | python3 -m json.tool # Réponse JSON réelle (extrait) { "count": 6, "next": null, "results": [ { "id": 1, "titre": "Circuits LC — Résonance en Radioamateurisme", "slug": "circuit-lc", "categorie": "radio", "date": "2026-04-11", "auteur": "admin" }, { "id": 2, "titre": "WSPR — Weak Signal Propagation Reporter", "slug": "wspr-weak-signal-propagation-reporter", "categorie": "radio", "date": "2026-04-11", "auteur": "admin" }, { "id": 3, "titre": "APRS — Automatic Packet Reporting System", "slug": "aprs-automatic-packet-reporting-system", "categorie": "radio", "date": "2026-04-11", "auteur": "admin" } ] }
Consommer cette API depuis JavaScript (fetch)
// Afficher les articles radio depuis l'API dans une page WordPress fetch('https://django.jerko.fr/api/articles/?categorie=radio') .then(r => r.json()) .then(data => { console.log(`${data.count} articles dans la catégorie radio`); data.results.forEach(article => { console.log(article.titre, article.date); }); });
Projet concret : un DX Cluster web avec Django
Le DX Cluster est un outil incontournable pour le radioamateur qui chasse les stations rares : il agrège en temps réel les spots émis par des opérateurs du monde entier, signalant qu’une station est active sur une fréquence donnée. Traditionnellement accessible via telnet, le DX Cluster se prête parfaitement à une mise en valeur web grâce à Django. Le déploiement DXSpider est disponible ici : f4hxn.fr/dx-spider/.
L’architecture retenue repose sur deux composants qui collaborent via une API REST :
cluster.jerko.fr
Script Python
Se connecte à un nœud DXSpider parent, ingère les spots en temps réel et les stocke en base de données
/api/spots/
Django REST API
DRF + Nginx
Expose les spots en JSON, consommables par WordPress, une appli mobile ou n’importe quel client web
Le modèle Django d’un spot DX
# dxcluster/models.py from django.db import models class Spot(models.Model): dx_call = models.CharField(max_length=20) # indicatif DX spotter freq = models.FloatField() # fréquence en kHz dx_station = models.CharField(max_length=20) # station spottée comment = models.CharField(max_length=128, blank=True) timestamp = models.DateTimeField(auto_now_add=True) class Meta: ordering = ['-timestamp'] # les plus récents en premier def __str__(self): return f"{self.dx_call} — {self.dx_station} — {self.freq} kHz"
Requête sur l’API des spots
# Les 10 derniers spots curl -s https://cluster.jerko.fr/api/spots/?limit=10 | python3 -m json.tool { "count": 4821, "results": [ { "dx_call": "F4HXN", "freq": 14025.0, "dx_station": "TM5REF", "comment": "59 CW TNX", "timestamp": "2026-05-19T08:42:11Z" } ] }
Afficher les spots en direct dans WordPress
<!-- Bloc HTML Gutenberg --> <div id="dx-spots" style="font-family:DM Sans,sans-serif;"></div> <script> (function() { fetch('https://cluster.jerko.fr/api/spots/?limit=10') .then(r => r.json()) .then(data => { document.getElementById('dx-spots').innerHTML = '<table><tr><th>Spotter</th><th>DX</th><th>Fréq. kHz</th><th>Info</th></tr>' + data.results.map(s => `<tr><td>${s.dx_call}</td><td><b>${s.dx_station}</b></td> <td>${s.freq}</td><td>${s.comment}</td></tr>` ).join('') + '</table>'; }); })(); </script>
Ce widget peut s’enrichir : filtrage par bande, rafraîchissement automatique toutes les 30 secondes avec setInterval(), mise en évidence des nouvelles entités DXCC… Le tout sans modifier WordPress — uniquement en jouant sur l’API Django et quelques lignes de JavaScript.
Mise en pratique : django.jerko.fr
L’instance disponible à l’adresse https://django.jerko.fr illustre concrètement ce que l’on vient de décrire. Elle tourne sur un serveur Gunicorn derrière un reverse-proxy Nginx, déployée dans une VM Proxmox. Voici comment tout ça s’articule.
La pile technique
| Couche | Outil | Rôle |
|---|---|---|
| Application | Django 4.x + DRF | Logique métier, ORM, API REST |
| Serveur WSGI | Gunicorn | Fait le pont entre Nginx et Django |
| Reverse proxy | Nginx | SSL/TLS, fichiers statiques, routage |
| Base de données | SQLite / PostgreSQL | Persistance des données |
| Infrastructure | Proxmox VM Ubuntu | Virtualisation, isolation, snapshots |
Structure du projet Django (arborescence simplifiée)
mon-api/ ├── manage.py # CLI Django (migrations, runserver…) ├── mon_api/ # Configuration principale │ ├── settings.py # BDD, apps installées, debug, CORS… │ ├── urls.py # Routage global des URLs │ └── wsgi.py # Point d'entrée Gunicorn └── logbook/ # Exemple d'application Django ├── models.py # Définition de la table QSO ├── serializers.py # Conversion objet Python ↔ JSON ├── views.py # Logique des endpoints API └── urls.py # Routes locales à cette app
Un modèle de QSO en 10 lignes
# logbook/models.py from django.db import models class QSO(models.Model): callsign = models.CharField(max_length=20) band = models.CharField(max_length=10) # ex: "40m" mode = models.CharField(max_length=10) # FT8, SSB, CW… locator = models.CharField(max_length=8, blank=True) rst_sent = models.IntegerField(default=59) rst_rcvd = models.IntegerField(default=59) date_time = models.DateTimeField(auto_now_add=True) def __str__(self): return f"{self.callsign} – {self.band} – {self.mode}"
Après python manage.py makemigrations && python manage.py migrate, Django crée automatiquement la table SQL correspondante. Aucune requête DDL à écrire à la main.
Intégrer l’API Django dans WordPress
L’API REST Django et WordPress coexistent très bien : l’un gère les données métier, l’autre gère la présentation éditoriale. Le lien entre les deux se fait côté navigateur via JavaScript — aucune modification WordPress côté serveur n’est nécessaire.
Exemple : widget dans un article WordPress (bloc HTML)
<!-- À coller dans un bloc HTML Gutenberg --> <div id="dx-widget" style="font-family:DM Sans,sans-serif;padding:1rem;"></div> <script> (function() { const API = 'https://django.jerko.fr/api/spots/?limit=10'; fetch(API) .then(r => r.json()) .then(data => { const el = document.getElementById('dx-widget'); el.innerHTML = data.results.map(s => `<p><strong>${s.dx}</strong> — ${s.freq} kHz — ${s.spotter}</p>` ).join(''); }); })(); </script>
Astuce CORS — Pour que le navigateur accepte la requête vers un domaine différent (django.jerko.fr depuis f4hxn.fr), il faut autoriser les origines dans Django :
# settings.py INSTALLED_APPS += ['corsheaders'] MIDDLEWARE = ['corsheaders.middleware.CorsMiddleware', ...autres...] CORS_ALLOWED_ORIGINS = ['https://f4hxn.fr', 'https://frimousse.net']
Déploiement pas à pas sur Proxmox / Ubuntu
La procédure suivante correspond à la mise en production effective de django.jerko.fr.
Créer la VM et installer Python
sudo apt install python3-pip python3-venv -y
Créer l’environnement virtuel et installer Django
python3 -m venv /opt/mon-api/venv source /opt/mon-api/venv/bin/activate pip install django djangorestframework gunicorn django-cors-headers
Créer le projet et appliquer les migrations
django-admin startproject mon_api /opt/mon-api cd /opt/mon-api python manage.py migrate python manage.py createsuperuser
Configurer Gunicorn comme service systemd
# /etc/systemd/system/gunicorn-monapi.service
[Service]
WorkingDirectory=/opt/mon-api
ExecStart=/opt/mon-api/venv/bin/gunicorn \
--workers 3 --bind unix:/run/gunicorn-monapi.sock \
mon_api.wsgi:application
Configurer le vhost Nginx
server {
listen 443 ssl;
server_name django.jerko.fr;
location / {
proxy_pass http://unix:/run/gunicorn-monapi.sock;
proxy_set_header Host $host;
}
location /static/ {
alias /opt/mon-api/staticfiles/;
}
}
Ce qu’il faut retenir
Django n’est pas un outil qui remplace WordPress — ce sont deux mondes différents. WordPress excelle pour la gestion de contenu éditorial, le blog, les pages statiques. Django excelle quand vous avez des données métier complexes à modéliser, exposer et manipuler via une API.
Pour un radioamateur actif — qui génère des logs, des spots, des trames WSPR, des données ADS-B — Django ouvre des perspectives intéressantes : construire son propre back-end de données, l’exposer via une API REST propre, et l’intégrer dans n’importe quelle interface, y compris ses pages WordPress existantes, avec quelques lignes de JavaScript.
Le projet django.jerko.fr en est la démonstration en conditions réelles : une API Python déployée sur infrastructure Proxmox, accessible depuis n’importe quel client, prête à être enrichie selon les besoins.
Ressources pour aller plus loin
Documentation officielle : docs.djangoproject.com • DRF : django-rest-framework.org • CORS : pypi.org/project/django-cors-headers
Un grand merci à Yoann F4JTV qui m’a fait découvrir Django et m’a donné l’envie de creuser ce framework.
C’est souvent par un échange entre radioamateurs passionnés qu’on franchit le pas vers de nouveaux horizons techniques — et Django en est la preuve.



