Formation Django. Maxime Arthaud basé sur les slides de V. Angladon et V. Duvert. Jeudi 7 novembre 2013



Documents pareils
Django. Framework de développement Web

Sécurité des sites Web Pas un cours un recueil du net. INF340 Jean-François Berdjugin

les techniques d'extraction, les formulaires et intégration dans un site WEB

Module Com231A - Web et Bases de Données Notion 5 : Formulaires et utilisation des Bases de Données avec PHP

LANGAGUE JAVA. Public Développeurs souhaitant étendre leur panel de langages de programmation

Module BD et sites WEB

Bases de Données et Internet

SYSTÈMES D INFORMATIONS

Guide d implémentation. Réussir l intégration de Systempay

Gestion de stock pour un magasin

Attaques applicatives

Formation Webase 5. Formation Webase 5. Ses secrets, de l architecture MVC à l application Web. Adrien Grand <jpountz@via.ecp.fr> Centrale Réseaux

INTRODUCTION A JAVA. Fichier en langage machine Exécutable

Modélisation PHP Orientée Objet pour les Projets Modèle MVC (Modèle Vue Contrôleur) Mini Framework

Projet en nouvelles technologies de l information et de la communication

Principales failles de sécurité des applications Web Principes, parades et bonnes pratiques de développement

Drupal (V7) : principes et petite expérience

Initiation à la programmation en Python

Les solutions de paiement CyberMUT (Crédit Mutuel) et CIC. Qui contacter pour commencer la mise en place d une configuration de test?

INTERNET est un RESEAU D ORDINATEURS RELIES ENTRE EUX A L ECHELLE PLANETAIRE. Internet : interconnexion de réseaux (anglais : net = réseau)

Créer une base de données vidéo sans programmation (avec Drupal)

Devenez un véritable développeur web en 3 mois!

PHP 5.4 Développez un site web dynamique et interactif

Sécurité des applications web. Daniel Boteanu

Soyez accessible. Manuel d utilisation du CMS

Hébergement de site web Damien Nouvel

Administration du site (Back Office)

BTS S.I.O PHP OBJET. Module SLAM4. Nom du fichier : PHPRévisionObjetV2.odt Auteur : Pierre Barais

25 mars. Tutoriel sur Laravel. Préparé par : Lydiane Beaulne-Bélisle. Ceci est un tutorial qui montre comment débuter avec le Framework PHP Laravel.

STAGE2 STAGIAIRE / NIKOLAOS TSOLAKIS. 16/02/2015 : choix des outils nécessités pour l application : Didier Kolb, le maitre de stage

Déploiement des manuels numériques sur tablette. Mode d emploi intégrateur / administrateur

Par KENFACK Patrick MIF30 19 Mai 2009

Refonte des sites internet du SIEDS

e-obs : Conception et utilisation Rémy Decoupes Ether // ums3365

BES WEBDEVELOPER ACTIVITÉ RÔLE

Maarch Framework 3 - Maarch. Tests de charge. Professional Services. 11, bd du Sud Est Nanterre

PLATEFORME DE GESTION DE CONGRÈS SCIENTIFIQUES. 12 mars 2015

Sage 100 CRM - Guide de la Fusion Avancée Version 8. Mise à jour : 2015 version 8

Django et PostgreSQL sous la charge

Introduction. PHP = Personal Home Pages ou PHP Hypertext Preprocessor. Langage de script interprété (non compilé)

Programmation Web. Madalina Croitoru IUT Montpellier

Les outils de création de sites web

Sommaire Accès via un formulaire d'identification... 4 Accès en mode SSO... 5 Quels Identifiant / mot de passe utiliser?... 6

Spétechs Mobile. Octobre 2013

Serveur d Applications Web : WebObjects

Projet 2. Gestion des services enseignants CENTRE D ENSEIGNEMENT ET DE RECHERCHE EN INFORMATIQUE. G r o u p e :

Manuel : Comment faire sa newsletter

Automatisation de l administration système

SYNC FRAMEWORK AVEC SQLITE POUR APPLICATIONS WINDOWS STORE (WINRT) ET WINDOWS PHONE 8

4. Personnalisation du site web de la conférence

WEB & DÉVELOPPEMENT LES BASES DU WEB LE LANGAGE HTML FEUILLES DE STYLES CSS HISTORIQUE D INTERNET ET DU WEB LES DIFFÉRENTS LANGAGES

Installation d un serveur HTTP (Hypertext Transfer Protocol) sous Débian 6

Master1 ère année. Réseaux avancés I. TP nº5 filière ISICG

Cursus 2013 Déployer un Content Management System

PHP 4 PARTIE : BASE DE DONNEES

GUIDE D INSTALLATION DE L APPLICATION GECOL SUR

S7 Le top 10 des raisons d utiliser PHP pour moderniser votre existant IBM i

1 Définition et Appel d une fonction. V. Phan Luong. Cours 4 : Fonctions

3W Academy Programme de Formation Développeur Intégrateur web Total : 400 heures

Un site web collaboratif avec Drupal. Judith Hannoun - Journées INSHS 16 Octobre 2012

L envoi d un formulaire par courriel. Configuration requise Mail Texte Mail HTML Check-list

Vulnérabilités et solutions de sécurisation des applications Web

PHP CLÉS EN MAIN. 76 scripts efficaces pour enrichir vos sites web. par William Steinmetz et Brian Ward

Formation. Module WEB 4.1. Support de cours

WIMS. Découvrir et utiliser

Description des pratiques à adopter pour la mise à jour du layout en utilisant le gestionnaire de conception de Sharepoint 2013

TP 1. Prise en main du langage Python

Failles des applications Web. Ce document est extrait du travail de diplôme de M. DIZON dans l état.

TP JAVASCRIPT OMI4 TP5 SRC

Formulaire pour envoyer un mail

Guide d utilisation. Version 1.1

Introduction aux concepts d ez Publish

SQL MAP. Etude d un logiciel SQL Injection

Présentation du PL/SQL

Guide d utilisation 2012

Tolérance aux Fautes des Grappes d Applications J2EE. Applications Internet dynamiques

Utiliser un tableau de données

Compte Rendu d intégration d application

Stockage du fichier dans une table mysql:

Chapitre 1 Qu est-ce qu une expression régulière?

Mise en place d un serveur Proxy sous Ubuntu / Debian

Manuel utilisateur du logiciel PrestaConnect.

Cours Linux. Cours en ligne Administrateur Systèmes Linux. Académie Libre

Comparatif CMS. Laurent BAUREN S Bérenger VIDAL Julie NOVI Tautu IENFA

ENDNOTE X2 SOMMAIRE. 1. La bibliothèque EndNote 1.1. Créer une nouvelle bibliothèque 1.2. Ouvrir une bibliothèque EndNote 1.3. Fermer une bibliothèque

PHP et mysql. Code: php_mysql. Olivier Clavel - Daniel K. Schneider - Patrick Jermann - Vivian Synteta Version: 0.9 (modifié le 13/3/01 par VS)

Présentation du langage et premières fonctions

Soon_AdvancedCache. Module Magento SOON. Rédacteur. Relecture & validation technique. Historique des révisions

CAHIER DES CHARGES D IMPLANTATION

MYXTRACTION La Business Intelligence en temps réel

Découvrir le CMS. et l utiliser dans une approche pro!

CMS Open Source : état de l'art et méthodologie de choix

webmestre : conception de sites et administration de serveurs web 42 crédits Certificat professionnel CP09

Joomla! Création et administration d'un site web - Version numérique

Note de synthèse. Développement web sur le CMS Prestashop. Stage du 17 mai au 25 juin Entreprise decoratzia.com 15 rue Erlanger Paris

Classe ClInfoCGI. Fonctions membres principales. Gestion des erreurs

ContactForm et ContactFormLight - Gestionnaires de formulaire pour Prestashop Edité par ARETMIC S.A.

GOOGLE ANALYTICS. Ajout du code de suivi sur PowerBoutique. Ajout du code de suivi Google Analytics. Page 1 / 7 TUTO / GOOGLE ANALYTICS

Transcription:

Maxime Arthaud basé sur les slides de V. Angladon et V. Duvert Jeudi 7 novembre 2013 http://www.bde.enseeiht.fr/clubs/net7/ supportformations/django/2013 Maxime Arthaud basé sur les slides de V. Angladon et V. Duvert Jeudi 7 novembre 2013 http://www.bde.enseeiht.fr/clubs/net7/ supportformations/django/2013

Bibliothèque =/= Framework : bibliothèque : collection de fonctions + classes spécialisées framework : ensemble de fonctions + classes + méthodologie. En général on ne peut pas changer de framework sans repartir à zéro.

Tout le monde sait ce qu est une base de donnée? BD = entité dans laquelle on peut stocker des données structurées selon un modèle prédéfini. Base = ensemble de tables. Table = tableau avec des colonnes prédéfinies (nom + type). permettent de faire des opérations complexes sur ces données : tri, sélection/filtrage à l aide d un langage,... permet accès concurrents, protection contre la corruption, récupération de données si requête interrompue, sécurité,... C est beaucoup mieux que de gérer des fichiers

CMS = gestionnaire de contenu (SPIP, Joomla, Drupal,...) site dynamique tout prêt (personnalisable) ou il suffit de rajouter du contenu via une interface d administration.

Attention Version actuelle : Django 1.6 (Python2 ou Python3) Utilisez Django 1.5 avec python 2 >> Architecture Attention Version actuelle : Django 1.6 (Python2 ou Python3)

Attention Version actuelle : Django 1.6 (Python2 ou Python3) Utilisez Django 1.5 avec python 2 >> Architecture Attention Version actuelle : Django 1.6 (Python2 ou Python3)

Architecture Architecture Architecture Requête URL Vue Modèle Template Réponse (HTML) Requête URL Vue Modèle Template Réponse (HTML) Fonctionnement de Django : slide le plus important de la formation. l utilisateur charge une page de votre serveur serveur HTTP a plusieurs instance de Django prêtes à traiter des requêtes Django créé un objet Requête représentant votre requête qui passe à travers divers couches d intergiciels modifiant éventuellement cet objet Maintenant j en viens à ce qui est important et figure sur le schéma Django parse l url et cherche la vue lui correspondant Toute l essences du site réside dans les vues qui peuvent récupérer des données de bases de données et effectuer un rendu HTML avec des templates éventuellement. La vue précédemment sélectionnée renvoie un objet RéponseHTTP Cet objet repasse à travers les couches d intergiciels. >> 1e projet

Créer un site Django Créer un site Django Créer un site Django $ django-admin.py startproject monsite $ tree monsite/ monsite +-- manage.py +-- monsite +-- init.py +-- settings.py +-- urls.py +-- wsgi.py $ cd monsite $ python2 manage.py runserver [...] $ django-admin.py startproject monsite $ tree monsite/ monsite +-- manage.py +-- monsite +-- init.py +-- settings.py +-- urls.py +-- wsgi.py $ cd monsite $ python2 manage.py runserver [...] >> 1e vue

Votre 1e vue! Votre 1e vue! Votre 1e vue! 1 Créez un fichier monsite/views.py 2 Copiez y le code suivant : # -*- coding: utf-8 -*- from django.http import HttpResponse def home(request): return HttpResponse("Hello") Vue renvoie un objet RéponseHTTP 1 Créez un fichier monsite/views.py 2 Copiez y le code suivant : Oui mais il faut dire quelque part qu il faut utiliser cette vue quand une url donnée est demandée. >> urls # -*- coding: utf-8 -*- from django.http import HttpResponse def home(request): return HttpResponse("Hello")

La gestion des URLs La gestion des URLs La gestion des URLs 1 Ouvrez le fichier monsite/urls.py 2 Modifiez le code pour avoir : from django.conf.urls.defaults import patterns, \ include, url urlpatterns = patterns(, url(r ^$, monsite.views.home ), ) 1 Ouvrez le fichier monsite/urls.py 2 Modifiez le code pour avoir : from django.conf.urls.defaults import patterns, \ include, url urlpatterns = patterns(, url(r ^$, monsite.views.home ), ) C est là qu on fait l aiguillage des urls (selon regexp matchée) vers une vue. Pas besoin de / a la fin des urls le r signifie que l on considere la chaine de l expression reguliere en mode "raw" ie \t n est pas interprete comme le caractere de tabulation mais comme \ suivi de t, permet d écrire \b au lieu de \\b (car \ doit être échappé en Python) M? signifie M est optionnel Formation ou ;. tout Django char sauf \n ; \w = mot alphanum La gestion des URLs M0,3 : on peut reconnaitre 0 ou 1 ou 2 ou 3 M consécutifs 1 Ouvrez le fichier monsite/urls.py 2 M3 : reconnaitre exactement 3 M consécutifs Modifiez le code pour avoir : M+ : 1 ou 2 ou... M consécutifs, M* : 0 ou 1 ou 2... urlpatterns = patterns(, La gestion des URLs from django.conf.urls.defaults import patterns, \ include, url ) url(r ^$, monsite.views.home ),

URLs et expressions régulières URLs et expressions régulières URLs et expressions régulières #... suite de l urlpattern dans urls.py (r ^annee/(\d{4})$, monsite.views.annee ), (r ^aff/(?p<texte>.+)/$, monsite.views.aff ), # vues associees dans views.py def annee(request, year): return HttpResponse("On est en "+year) def aff(request, texte): return HttpResponse("Bonjour "+texte) #... suite de l urlpattern dans urls.py (r ^annee/(\d{4})$, monsite.views.annee ), (r ^aff/(?p<texte>.+)/$, monsite.views.aff ), Si on continue comme ça : urls.py de 500 lignes. Donc découper projet en modules/apps >> 1e app # vues associees dans views.py def annee(request, year): return HttpResponse("On est en "+year) def aff(request, texte): return HttpResponse("Bonjour "+texte)

Première application Première application Première application $ python2 manage.py startapp monapp $ ls monapp init.py models.py tests.py views.py 1 ajouter l application dans le tuple INSTALLED_APPS de settings.py 2 bonne pratique : monapp/urls.py >> config des urls $ python2 manage.py startapp monapp $ ls monapp init.py models.py tests.py views.py 1 ajouter l application dans le tuple INSTALLED_APPS de settings.py 2 bonne pratique : monapp/urls.py

Découplage des URLs Découplage des URLs Découplage des URLs # Rajouter cet urlpattern dans monsite/urls.py url(r ^monapp/, include( monapp.urls )) # monapp/urls.py from django.conf.urls import patterns, include, url urlpatterns = patterns( monapp.views, url(r ^$, index ), url(r ^info$, info ), ) # Rajouter cet urlpattern dans monsite/urls.py url(r ^monapp/, include( monapp.urls )) # monapp/urls.py from django.conf.urls import patterns, include, url Le premier paramètre de patterns est un prefix pour les noms des vues. Pour le moment on sait afficher des chaines de caractère et gérer des urls. Avant de passer aux templates, regardons les modèles. >> modèle urlpatterns = patterns( monapp.views, url(r ^$, index ), url(r ^info$, info ), )

Création d un modèle Création d un modèle Création d un modèle 1 Configurer la base de donnée dans settings.py 2 Créer les modèles 3 Générer les tables à partir du modèle Page de référence sur la configuration des bases de données : https://docs.djangoproject.com/en/dev/ref/settings/#databases Page de référence sur les champs des modèles : https://docs.djangoproject.com/en/dev/ref/models/fields/ 1 Configurer la base de donnée dans settings.py 2 Créer les modèles 3 Générer les tables à partir du modèle Je saute la configuration de settings.py car bien commenté possibilité configuration plusieurs DB. Modèle = classe qui définie une table. les instances de cette classe sont des lignes de la table. La génération des tables est automatique. >> 1e modèle Page de référence sur la configuration des bases de données : https://docs.djangoproject.com/en/dev/ref/settings/#databases Page de référence sur les champs des modèles : https://docs.djangoproject.com/en/dev/ref/models/fields/

Premier modèle Premier modèle Premier modèle # monapp/models.py from django.db import models class Article(models.Model): nom = models.charfield(verbose_name="nom de l article"\, max_length=128) description = models.textfield(max_length=512) prix = models.decimalfield(decimal_places=2, max_digits=6) couleurs = models.textfield(default="blue") ecole = models.foreignkey(ecole, editable=false) def unicode (self): return self.nom # monapp/models.py from django.db import models class Article(models.Model): nom = models.charfield(verbose_name="nom de l article"\, max_length=128) description = models.textfield(max_length=512) prix = models.decimalfield(decimal_places=2, max_digits=6) couleurs = models.textfield(default="blue") ecole = models.foreignkey(ecole, editable=false) def unicode (self): return self.nom Tiré du code du portail (modifié) CharField, TextField, DecimalField, ForeignKey max_length, default verbose_name : nom utilisé pour le formulaire blank : peut être laissé vide/null ou pas editable : pas apparaître dans le formulaire généré, ni dans l interface d admin Méthode unicode () : gérer comment afficher l objet, ex dans un print(). Idem que str () mais renvoie une chaîne utf-8. Les chaînes des DB sont converties en unicode par Django. >> création de la db

Création de la base de donnée Création de la base de donnée Création de la base de donnée Création de la base : $ python2 manage.py syncdb Voir les commandes SQL exécutées : $ python2 manage.py sql monapp Visualiser une base de donnée sqlite : $ sqliteman mabase.sqlite Création de la base : >> 1e requete $ python2 manage.py syncdb Voir les commandes SQL exécutées : $ python2 manage.py sql monapp Visualiser une base de donnée sqlite : $ sqliteman mabase.sqlite

Premières requêtes Premières requêtes Premières requêtes $ python2 manage.py shell Manipuler les modèles : Modele.objects.all() Modele.objects.get() Modele.objects.filter() entree.delete() entree.save() Pages de référence : https://docs.djangoproject.com/en/1.3/topics/db/queries/ https://docs.djangoproject.com/en/1.3/ref/models/querysets/ $ python2 manage.py shell Manipuler les modèles : En va faire ça ensemble. Lançons un shell particulier qui va mettre en place l environnement. >> template Modele.objects.all() Modele.objects.get() Modele.objects.filter() entree.delete() entree.save() Pages de référence : https://docs.djangoproject.com/en/1.3/topics/db/queries/ https://docs.djangoproject.com/en/1.3/ref/models/querysets/

Template = page html liée à une vue 1 configurer TEMPLATE_DIRS dans settings.py 2 définir les variables affichées/utilisées par le template et les regrouper dans un dictionnaire 3 changer la vue pour quelle renvoie render(request, montemplate.html, dictionnaire) Pages de référence : https://docs.djangoproject.com/en/dev/ref/templates/api/ https://docs.djangoproject.com/en/dev/ref/templates/builtins/?f Template = page html liée à une vue >> exemple 1 configurer TEMPLATE_DIRS dans settings.py 2 définir les variables affichées/utilisées par le template et les regrouper dans un dictionnaire 3 changer la vue pour quelle renvoie render(request, montemplate.html, dictionnaire) Pages de référence : https://docs.djangoproject.com/en/dev/ref/templates/api/ https://docs.djangoproject.com/en/dev/ref/templates/builtins/?from=olddocs

Exemple d utilisation Exemple d utilisation Exemple d utilisation La vue from monapp.models import Article from django.shortcuts import render def index(request): c = { articles : Article.objects.all()} return render(request, index.html, c) Le template index.html <h1>liste des articles</h1> <ul> {% for a in articles %} <li>{{ a.nom }}</li> {% endfor %} </ul> La vue from monapp.models import Article from django.shortcuts import render def index(request): c = { articles : Article.objects.all()} return render(request, index.html, c) Le template index.html <h1>liste des articles</h1> <ul> {% for a in articles %} <li>{{ a.nom }}</li> {% endfor %} </ul> {{ }} : accès variables {% %} : commande de template Remarquez le for comme si on était en Python Notez la syntaxe objet.attribut (f.id), idem pour accès liste/tuple : f.0, f.1... balise url, if ou else possibilité d appliquer des fonctions (filtres) à des variables via >> blocs

Etendre des blocs Etendre des blocs Etendre des blocs Page principale, main.html <html lang="fr"> <head><title>{% block title %}{% endblock %}</title></head> <body> <h1>bienvenue!</h1> {% block content %}{% endblock %} </body> </html> Page affichage.html qui va étendre main.html {% extends "main.html" %} {% block title %}Le titre de ma page{% endblock %} {% block content %} Du contenu ici. {% endblock %} Page principale, main.html <html lang="fr"> <head><title>{% block title %}{% endblock %}</title></head> <body> <h1>bienvenue!</h1> {% block content %}{% endblock %} </body> </html> Page affichage.html qui va étendre main.html {% extends "main.html" %} {% block title %}Le titre de ma page{% endblock %} {% block content %} Du contenu ici. {% endblock %} le contenu de affichage.html va etre inséré dans main.html >> formulaires

A la main A la main A la main Définition du formulaire, forms.py from django import forms class InscriptionForm(ModelForm): login = forms.charfield(required=true) password = forms.charfield(label= Mot de passe, required=t code = forms.integerfield() Son template, edit.html <form action="" method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="submit" /> </form> Définition du formulaire, forms.py from django import forms class InscriptionForm(ModelForm): login = forms.charfield(required=true) >> vue du formulaire password = forms.charfield(label= Mot de passe, required=true, widget=forms.passwordinput) code = forms.integerfield() Son template, edit.html <form action="" method="post"> {% csrf_token %} {{ form.as_p }} <input type="submit" value="submit" /> </form> On peut utiliser request.get et request.post, mais ce n est pas propre. Form = Même chose que les modèles. form.as_table, form.as_ul,..

Vue d un formulaire Vue d un formulaire Vue d un formulaire from django.shortcuts import redirect def inscription(request): if request.method == POST : form = InscriptionForm(request.POST) if form.is_valid(): # Faire qqch avec les donnees.. return redirect( monapp.views.merci ) else: form = InscriptionForm() return render(request, inscription.html, { form : form}) form.cleaned_data est un dictionnaire avec la valeur des champs from django.shortcuts import redirect >> formulaire généré à partir d un modèle def inscription(request): if request.method == POST : form = InscriptionForm(request.POST) if form.is_valid(): # Faire qqch avec les donnees.. return redirect( monapp.views.merci ) else: form = InscriptionForm() return render(request, inscription.html, { form : form})

A partir d un modèle A partir d un modèle A partir d un modèle Formulaire, forms.py class ArticleForm(models.ModelForm): class Meta: model = Article fields = ( login, password, code ) Vue, views.py objet = get_object_or_404(article, pk=1) if request.method == POST : form = ArticleForm(request.POST, instance=objet) if form.is_valid(): form.save() return redirect(objet) else: form = ArticleForm(instance=objet) return render(request, edit.html, { form : form}) Formulaire, forms.py class ArticleForm(models.ModelForm): class Meta: model = Article fields = ( login, password, code ) Vue, views.py objet = get_object_or_404(article, pk=1) if request.method == POST : form = ArticleForm(request.POST, instance=objet) if form.is_valid(): form.save() return redirect(objet) else: form = ArticleForm(instance=objet) return render(request, edit.html, { form : form}) Formulaire généré automatiquement, customisable Dans le cas de l ajout, ne pas passer en paramètre un objet get_object_or_404 permet de retourner un objet, ou erreur 404 code-snippet, pas à retenir! >> admin

1 Décommenter les lignes concernant l interface d administration dans settings.py et urls.py 2 Mettre à jour les tables (syncdb) 3 Pour chaque application, indiquer les modèles pris en charge par l interface d administration via un fichier admin.py comme suit : from monapp.models import Modele1, Modele2 from django.contrib import admin admin.site.register(modele1) admin.site.register(modele2) 1 Décommenter les lignes concernant l interface d administration dans settings.py et urls.py 2 Mettre à jour les tables (syncdb) Générée automatiquement, customisable :) >> exo 3 Pour chaque application, indiquer les modèles pris en charge par l interface d administration via un fichier admin.py comme suit : from monapp.models import Modele1, Modele2 from django.contrib import admin admin.site.register(modele1) admin.site.register(modele2)

Exercice : FaceMash Exercice : FaceMash Exercice : FaceMash Cahier des charges, fonctions à implémenter : ajouter/éditer un utilisateur (Nom, adresse mail, photo) via un formulaire visualiser une liste des utilisateurs triée selon leur score visualiser le profil d un utilisateur enregistrer les votes : date, vote, ip du votant (on est méchant) afficher la liste des votes vote : afficher les photos de 2 utilisateurs choisis aléatoirement, le vote s effectue en cliquant sur l une des photos interface d administration Cahier des charges, fonctions à implémenter : ajouter/éditer un utilisateur (Nom, adresse mail, photo) via un formulaire visualiser une liste des utilisateurs triée selon leur score visualiser le profil d un utilisateur enregistrer les votes : date, vote, ip du votant (on est méchant) afficher la liste des votes vote : afficher les photos de 2 utilisateurs choisis aléatoirement, le vote s effectue en cliquant sur l une des photos interface d administration Vous pouvez partir si vous voulez, vous avez la correction. L intérêt de faire l exo ici est qu on peut vous aider... FaceMash consiste à... Une partie du code vous est donnée. environ 200 lignes de code Python Attention, settings.py à compléter! script init.sh pour peupler votre base de donnée