Tutoriel : Partie 3 - Installation de Django
- Créer un environnement virtuel pour y installer Django
- Installer Django
- Créer un projet Django et une application
- Procéder à certains réglages de Django
- Créer les modèles et les vues de l’application
- Créer des fichiers css et html (templates)
- Capturer et stocker des images fixes prises par les caméras
- Lancer le site
- Pour éviter des problèmes de conflit entre python2 et python3, il est préférable d’installer Django dans un environnement virtuel.
- De manière à structurer les dossiers nous allons utiliser une arborescence de ce type :

- C’est dans folder que nous allons créer un environnement virtuel que nous appellerons folder_venv. Django sera installé dans cet environnement virtuel.
- Puis nous créerons un projet Django dans le dossier folder. Ce projet s’appellera project.
- Dans ce projet, nous créerons une application que nous appellerons camera.
- Vous pouvez choisir les noms folder et project que vous souhaitez (mais cela n’est pas souhaitable), à condition de les modifier dans le fichier configuration.ini (section
[paths], clésfolderetproject). - Il est très vivement conseillé de ne pas modifier le nom de l’application camera, sinon vous devrez changer le nom de l’application dans différents fichiers html ou python que nous créerons plus tard.
- Créer le dossier folder
mkdir ~/folder - Créer l’environnement virtuel
cd ~/folder python3 -m venv folder_venv(Ne pas omettre le 3 de python)
- Activer l’environnement virtuel
source ~/folder/folder_venv/bin/activate - L’invite de commande ne sera plus du type :
pi@Foo:~$mais du type
(folder_venv) pi@Foo:~$
N.B. : dorénavant, lorsque les commandes seront tapées dans l’environnement virtuel, elles seront précédées du symbole (venv)
Pour désactiver l’environnement virtuel taper la commande deactivate
(venv) deactivate
- Se mettre en environnement virtuel :
source ~/folder/folder_venv/bin/activate - Installer Django
(venv) python -m pip install Django - Django va s’installer dans l’environnement virtuel. Ici le 3 de la commande python n’est plus utile car il n’y a plus d’ambiguïté de choix, seul python3 étant installé dans l’environnement virtuel.
- Vérifier l’installation et la version
(venv) python -m django --version
qui doit renvoyer une sortie du type : 4.0.2 (en fonction de la version)
- Se mettre dans le répertoire folder (en environnement virtuel)
(venv) cd ~/folder - Créer le projet
(venv) django-admin startproject project - L’arborescence du dossier folder est la suivante :

- Se mettre dans le même dossier que celui contenant manage.py,
(venv) cd ~/folder/project - Créer l’application
(venv) python manage.py startapp camera - Django a créé un nouveau répertoire. L’arborescence est :

L’application camera va comporter huit vues, c’est à dire huit pages web différentes.
- accueil : la page d’accueil du site.
- historique : page présentant des photos prises à intervalle régulier par les trois caméras, sur une durée déterminée (par exemple, toutes les 5 minutes sur les 24 dernières heures)
- parHeure : page présentant les photos prises sur une durée déterminée (par exemple, toutes les 5 minutes sur les douze dernières heures)
- nuit : page présentant les photos prises entre le coucher et le lever du soleil (par exemple, toutes les 3 minutes du coucher au lever le lendemain)
- stream_1 : flux vidéo en direct de la première caméra
- stream_2: flux vidéo en direct de la deuxième caméra
- stream_py : flux vidéo en direct de la caméra py
- stream_AllCam : flux vidéo en direct des trois caméras
Ouvrir le fichier settings.py (vous n’avez pas besoin d’être en environnement virtuel)
nano ~/folder/project/project/settings.pyApporter les modifications suivantes
ALLOWED_HOSTS : ajouter l’IP locale de la Raspberry
ALLOWED_HOSTS = ['<local IP raspberry>']par exemple `['192.168.1.49']`INSTALLED_APPS : ajouter ‘camera.apps.CameraConfig’ dans la liste existante
INSTALLED_APPS = [ 'camera.apps.CameraConfig', 'django.contrib.admin', 'django.contrib.auth', 'django.contrib.contenttypes', 'django.contrib.sessions', 'django.contrib.messages', 'django.contrib.staticfiles', ]DATABASES : ajouter votre time-zone
DATABASES = { 'default': { 'ENGINE': 'django.db.backends.sqlite3', 'NAME': BASE_DIR / 'db.sqlite3', 'TIME_ZONE': 'Europe/Paris' } }
Ceci permet de régler des problèmes de prise en compte des dates par la base de données. Si vous optez pour une base de données autre que sqlite3, vous devrez réécrire les parties des scripts qui font appel au module sqlite3.
- LANGUAGE_CODE et TIME_ZONE : adapter la langue et la time-zone
LANGUAGE_CODE ='fr' TIME_ZONE = 'Europe/Paris' - STATICFILES_DIRS : ajouter en fin de fichier (en dessous de la ligne STATIC_URL par exemple)
STATICFILES_DIRS = [ BASE_DIR / "static", "/var/www/stock", ]
si vous avez gardé cette valeur de la clé stockde la section [paths] du fichier de configuration.
C’est dans ce dossier /var/www/stock que seront stockées les photos prises par les caméras.
- Les modèles vont permettre de définir les tables de la base de données.
- Nous allons créer deux modèles :
- un modèle Appareil qui caractérise chaque caméra
- un modèle Photo qui caractérise les photos qui vont être stockées
- Ouvrir le fichier
~/folder/project/camera/models.pynano ~/folder/project/camera/models.py - Supprimer son contenu
- Remplacer son contenu par celui du fichier
models.pydisponible ici. - Prendre en compte les modifications ; on crée la base de données et on effectue les migrations (en environnement virtuel)
(venv) python ~/folder/project/manage.py makemigrations (venv) python ~/folder/project/manage.py migrate - Créer les trois caméras
- Ouvrir le shell
(venv) python ~/folder/project/manage.py shell - Créer les caméras
>>> from camera.models import Appareil >>> c = Appareil(name="Cam_1") >>> c.save() >>> c = Appareil(name="Cam_2") >>> c.save() >>> c = Appareil(name="Cam_py") >>> c.save() - Vérifier que les trois caméras sont bien crées
>>> Appareil.objects.all() <QuerySet [<Appareil: Cam_1>, <Appareil: Cam_2>, <Appareil: Cam_py>]> - Quitter le shell :
Ctrl+D
- Ouvrir le shell
- Nous n’avons pas utilisé l’interface Admin de Django. Celle-ci nous est inutile, toutes les actions sur la base de données se feront directement par des scripts python.
- Ouvrir le fichier
nano ~/folder/project/project/urls.py - Modifier la ligne d’import et la ligne urlpatterns de la manière suivante
from django.contrib import admin from django.urls import path, include urlpatterns = [ path('camera/', include('camera.urls')), path('admin/', admin.site.urls), ] - Un exemplaire du fichier est disponible ici.
- Créer et ouvrir le fichier en écriture
nano ~/folder/project/camera/urls.py - Coller/copier dans ce fichier le contenu du fichier
urls.py(camera) disponible ici.
- Ouvrir le fichier
nano ~/folder/project/camera/views.py - Effacer son contenu et copier/coller le contenu du fichier views.py (V1) disponible ici.
- La vue historique (def historique(request)) permet de visualiser les captures de photos des trois caméras sur les N dernières heures en ne sélectionnant qu’une photo sur n, les photos étant prises à une fréquence f. Les paramètres N, n et f sont modifiables dans le fichier de configuration. Il s’agit des clés
historique,display_jouretcapturede la section[fréquences]. Si la clé historique est à 5, la clé display_jour à 2 et la clé capture à 60 cela signifie que les caméras prennent une photo toutes les 60 secondes et qu’on visualisera sur les 2 derniers jours une photo sur cinq (c’est à dire une photo toutes les 300 secondes). - La vue parHeure (def parHeure(request)) permettra de visualiser toutes les photos des trois caméras sur les N dernières heures prises à la fréquence f, sans sélection. N et f ont la même valeur que dans la vue historique. La présentation se fera en pagination.
- La vue nuit permet de visualiser les captures de photos entre le coucher du soleil et le lever du lendemain. Les photos sont prises à la fréquence f (la même que dans la vue historique) et on peut ne sélectionner qu’une photo sur p, p étant la clé
nuitde la section[fréquences]du fichier de configuration. - Les fonctions de streaming n’appellent aucun réglage, sauf l’adresse IP locale de la raspberry (clé
raspIPde la section[hosts]et les ports de sortie des flux (cléscam_1_port,cam_2_portetcam_py_portde la section[camera]) - Par défaut : N = 24 heures (clé display_jour=1, soit 24 heures), n = 4, p = 3, f = 60 (en secondes) ; les ports des flux sont par défaut 8081, 8082 et 8084.
- Les heures de lever et de coucher du soleil sont calculées à l’aide du module
suntimes - Installer le module suntimes (en environnement virtuel)
(venv) pip install suntimes - Si besoin installer jdcal et tzlocal (a priori les dépendances s’installent automatiquement)
(venv) pip install jdcal (venv) pip install tzlocal - Le constructeur
SunTimesdu modulesuntimesprend trois paramètres de localisation : longitude, latitude et altitude qu’il faut modifier dans le fichier de configuration. - Ouvrir le fichier de configuration
sudo nano /etc/camera/configuration.ini - Dans la section
[locate]modifier les valeurs par défaut par celles de votre lieu. Ces valeurs sont disponibles sur geoportail ou sur google earth.
- Dans la section
[hosts]chercher la cléraspIP - Remplacer la valeur
par l’IP locale de votre Raspberry
- Création des dossiers css et logo
- Les fichiers css sont situés dans
~/folder/project/camera/static/camera/css/ - Ce chemin paraît compliqué à première vue, mais il est le chemin recommandé dans les différentes tutoriels relatifs à Django. On suit cette procédure, même si la simplicité du site (une seule application) ne la justifie pas.
- Création des dossiers
cd ~/folder/project/camera mkdir static static/camera static/camera/css static/camera/logo
- Les fichiers css sont situés dans
- Remarques sur le fichier css :
- ce fichier a été récupéré à partir d’un site personnel construit antérieurement
- il y a des redondances et des classes superflues
- le design du site n’est pas optimal, loin s’en faut
- pour simplifier, tout le css a été regroupé dans un seul fichier
- il est possible de le fractionner en plusieurs fichiers, mais dans ce cas il faudra appeler chaque fichier dans le base.html
- Vous pouvez, bien sûr, modifier à votre convenance le css. Il faudra alors modifier l’appel des fichiers css dans le fichier
base.html(chapître suivant). - Création de global.css
- Créer et ouvrir en écriture le fichier global.css
nano ~/folder/project/camera/static/camera/css/global.css - Copier/coller dans l’éditeur de texte le contenu du fichier
global.cssdisponible ici
- Créer et ouvrir en écriture le fichier global.css
- Logo favicon
- La favicon est une image qui s’affiche dans la barre d’adresse web en regard de l’URL.
- Charger sur la Raspberry une image au format png d’environ 40x40 pixels
- Nommer l’image logo.png
- Déplacer l’image dans le dossier
~/folder/project/camera/static/camera/logo - Pour charger l’image logo.png située dans votre dossier /home/user/Bureau de votre ordinateur (par exemple) vers le dossier de la Raspberry taper dans un terminal la commande suivante :
scp /home/user/Bureau/logo.png pi@<local IP Raspberry>:/home/pi/folder/project/camera/static/camera/logo - En modifiant les chemins et l’IP de la Raspberry en fonction de vos paramètres ; à l’invite de commande, entrer le mot de passe de la Raspberry.
- Création du dossier templates
- Les fichiers html sont situés dans
~/folder/project/camera/templates/camera/ - Création des répertoires :
cd ~/folder/project/camera mkdir templates templates/camera
- Les fichiers html sont situés dans
- A propos de base.html
- base.html est le template (gabarit) de base dont vont hériter les autres templates.
- C’est dans ce gabarit que sont appelés les fichiers css et la favicon. Si vous avez modifié le chemin des fichiers css, c’est dans base.html que vous devez reporter ces modifications.
- De même, c’est dans ce gabarit que vous pouvez modifier l’aspect du menu, du header ou du footer (notamment, le nom qui apparaît en bas de page et le logo).
- Si vous modifiez le nom de ce gabarit ou si votre application ne s’appelle pas camera, vous devrez modifier en conséquence la première ligne
{% extends "camera/base.html" %}des autres gabarits.
- Création de base.html
- Créer et ouvrir en écriture le fichier base.html
nano ~/folder/project/camera/templates/camera/base.html - Copier/coller dans ce fichier le contenu du fichier
base.htmldisponible ici
- Créer et ouvrir en écriture le fichier base.html
- Procéder de même pour les autres fichiers html
accueil.htmldont le contenu est disponible icihistorique.htmldont le contenu est disponible icinuit.htmldont le contenu est disponible iciparHeure.htmldont le contenu est disponible icistream_1.htmldont le contenu est disponible icistream_2.htmldont le contenu est disponible icistream_py.htmldont le contenu est disponible icistream_AllCam.htmldont le contenu est disponible ici
- Créer le répertoire /var/www/stock
sudo mkdir /var/www/stock - Créer les sous-répertoires pour les différentes caméras
cd /var/www/stock sudo mkdir Camera_1 Camera_2 Camera_py - Changer le propriétaire de /var/www/stock
sudo chown -R pi /var/www/stock
- Ce script sera lancé au démarrage et tournera en boucle en effectuant :
- la capture des images pour chaque caméra à la fréquence choisie
- l’inscription dans la base de données des caractéristiques relatives à chaque photo (caméra, date de prise, nom de la photo, répertoire de stockage)
- Créer le script
- Créer et ouvrir en écriture le fichier getCamerasAndRegister.py
nano ~/script/getCamerasAndRegister.py - Copier/coller dans ce fichier le contenu du fichier
getCamerasAndRegister.pydisponible ici
- Créer et ouvrir en écriture le fichier getCamerasAndRegister.py
- Lancer le script au démarrage de la Raspberry
- Ouvrir le cron en édition
crontab -e - Ajouter la ligne suivante
@reboot python3 /home/pi/script/getCamerasAndRegister.py
- Ouvrir le cron en édition
Tous les jours on efface les images datant de plus de N jours, N étant la clé
delay-deletede la section[frequences]du fichier de configuration.Par défaut, la valeur de N est 2, c’est à dire qu’on ne conserve les images que deux jours.
Il est indispensable d’effectuer cette tâche régulièrement afin que la carte micro-SD ne soit pas saturée.
Créer et ouvrir en écriture le fichier suppressFiles.py
nano ~/script/suppressFiles.pyCopier/coller dans ce fichier le contenu du fichier
suppressFilesdisponible iciLancer le script tous les jours à 03H10 du matin (par exemple) dans le crontab
- Ouvrir le cron en édition
crontab -e- Ajouter la ligne suivante
10 03 * * * python3 /home/pi/script/suppressFiles.py
- Le script lance le serveur de Django au démarrage de la raspberry sur le port 8000 par défaut (paramétrable dans /etc/configuration.ini)
- Pour accéder au site depuis un appareil du réseau, vous devez avoir indiqué l’adresse IP locale de la raspberry dans ALLOWED_HOSTS du fichier ~/folder/project/project/settings.py (par exemple ALLOWED_HOSTS = [‘192.168.1.49’])
- Créer et ouvrir en écriture le fichier runDjango.py
nano ~/script/runDjango.py - Copier/coller le contenu du fichier runDjango.py disponible ici
- Lancer le script au démarrage dans le crontab
- Ouvrir le crontab en édition
crontab -e - Ajouter la ligne suivante
@reboot python3 /home/pi/script/runDjango.py - Il peut être nécessaire, notamment en fonction du modèle de Raspberry de donner un temps de latence au démarrage (ici 120 secondes)
@reboot sleep 120 && python3 /home/pi/script/runDjango.py
- Ouvrir le crontab en édition
- Rebouter le système
sudo reboot - Attendre que les scripts des différentes caméras soient lancés.
- Dans la barre d’adresse d’un navigateur taper
<local IP Raspberry>:8000/camera/(par exemple :192.168.1.49:8000/camera/) - Vous devez obtenir ce résultat :

- Si les caméras sont bien lancées, vous devez voir les flux en cliquant sur le bouton
En direct. Bien sûr, pour les autres pages html, au début vous ne verrez que peu ou pas d’images. - Au fil du temps, les différents historiques (Histoire, Heure par Heure et Nuit) pourront être longs à s’afficher, le nombre d’images à charger étant élevé. C’est, à l’évidence, une faiblesse des scripts.
- Lors du passage de l’horaire d’été à l’horaire d’hiver la même heure va être doublée
- Ceci ne pose pas de problème au niveau du stockage des photos : la photo qui portera le même nom écrasera la photo homonyme
- Par contre au niveau de la base de données, deux lignes vont exister pour une photo prise à la même heure
- Lorsqu’on voudra afficher les historiques, une erreur 500 sera renvoyée, Django ne sachant pas quelle image afficher
- Éteindre la raspberry avant le changement d’heure
- Rallumer la raspberry après le changement d’heure
- Après le changement d’heure, alors que l’erreur 500 va s’afficher, vider la table de la base de données contenant les informations des photos
- Se connecter en ssh à la raspberry
- Une fois connecté, se mettre dans le shell
squliteen tapant dans le terminal
pi@raspberry:~ $ sqlite3
- Ouvrir la base de données (à adapter si les différents noms ont été changés)
sqlite > .open "/home/pi/folder/project/db.sqlite3"
- Éventuellement vérifier le nom des tables de la base
sqlite > .tables
- Supprimer les donées de la table camera_photo (si ce nom a été conservé)
sqlite > DELETE FROM camera_photo;
- Quitter le shell sqlite
sqlite > Crtl+D
- Vérifier que l’historique ne renvoie pas d’erreur 500
- Au bout d’une minute de nouveaux enregistements sont inscrits dans la base et on peut les apercevoir dans la vue parHeure
- On dispose d’un site web qui fonctionne en local avec le serveur embarqué de Django.
- Ce site est accessible depuis les différents appareils du réseau local en tapant dans la fenêtre d’un navigateur web
<local IP Raspberry>:<port serveur Django>/camera - Si vous ne souhaitez pas accéder au site depuis l’extérieur, vous pouvez, de manière peu orthodoxe, en rester là. Mais il est souhaitable de passer à l’étape suivante.
- Installation d’un serveur Apache qui va prendre la main sur le serveur embarqué de Django.
- Installation du module mod-wsgi, interface entre Apache et Django
- Paramétrages de Apache et Django pour que le site soit accessible en production (et non plus en développement).