Commit 386f9fb9 authored by Bonnegent Sebastien's avatar Bonnegent Sebastien
Browse files

cours 2

parent 25e04534
* afficher le plan au début
* afficher l'objectif de ce qui doit être fait à la fin
Autres points:
* hijack
* dump/restore
* json initiale
* migration avancèe
* objects.latest()
* framework messages
∘ https://docs.djangoproject.com/fr/1.10/ref/contrib/messages/
* logging
* pytest
% Django par la pratique #01
% Sébastien Bonnegent
% version 17.10.22
% version 2018
# Prérequis
## Virtual Env #1
## L'environnement
Un environnement virtuel pour l'exécution de python.
### pipenv
- surcouche à venv et à pip
- gestion automatique du répertoire du virtualenv
- plusieurs groupes (prod, dev, ...)
- mise à jour facile
- gèle des versions utilisées
- outil recommandé par python.org
- https://www.youtube.com/embed/GBQAKldqgZs
. . .
### Création
~~~
$ python3 -m venv venv
$ mkdir vehicules
$ cd !$
$ pipenv --python 3.6
$ pipenv install django ipython
~~~
## Virtual Env #2
## Autres exemples d'utilisation
### Utilisation
~~~
$ # Entrée
$ source venv/bin/activate
$ # Sortie
$ desactivate
$ pipenv shell
$ pipenv run ipython
$ pipenv --venv
~~~
. . .
### Suppression
~~~
$ rm -rf venv
~~~
## Python In Python #1
### Commandes de base
### Mise à jour des dépendances
~~~
$ pip search django
$ pip install Django==1.11.5
$ pip uninstall django
$ pipenv update --outdated # affichage
$ pipenv update # réalisation
~~~
. . .
### Paquets intéressants
### Autres commandes
~~~
$ pip install django
$ pip install django-hijack django-hijack-admin
$ pip install sphinx sphinx-bootstrap-theme
$ pip install django-extensions
$ # Vérification des problèmes de sécurités connus (django 1.4.2 ?)
$ pipenv check
$ # arbre des dépendances
$ pipenv graph
~~~
## Python In Python #2
## Les indispensables
### État des paquets installés
### Devenir quelqu'un d'autres
~~~
$ pip freeze
alabaster==0.7.10
Babel==2.5.1
certifi==2017.7.27.1
chardet==3.0.4
Django==1.11.5
django-compat==1.0.14
django-extensions==1.9.1
django-hijack==2.1.4
...
$ pipenv install django-hijack django-hijack-admin
~~~
. . .
### Enregistrement de l'état
### Utilitaire
~~~
$ pip freeze > requirements.txt
$ pipenv install django-extensions
~~~
## Python In Python #3
. . .
### Installer / mettre à jour
### Pour les tests
~~~
$ pip install --upgrade --requirement requirements.txt
$ pipenv install pytest --dev
~~~
# Django
......@@ -86,60 +81,44 @@ $ pip install --upgrade --requirement requirements.txt
[^dj]: \tiny https://www.djangoproject.com/
## About
## À propos
### Qu'est ce que c'est ?
- framework pour applications web
- en python
- ORM: couche d'abstraction classes
- postgresql, mysql, sqlite, oracle, ...
- moteur de templates
- MVC
- framework python pour applications web
- ORM: couche d'abstraction entre les classes et la BD
- BD supportées: postgresql, mysql, sqlite, oracle, ...
- moteur de templates pour l'affichage (jinla)
. . .
## À propos
### Avantages
- gestion des migrations
- rapidité de mise en place
- factorisation du code
- interface d'administration automatique
- modèle MVC
- ...
. . .
### Inconvénients
- ?
## Création du projet
~~~
$ django-admin startproject conf
$ mv conf fwm
$ pipenv run django-admin startproject conf .
~~~
\center\includegraphics[height=2.5cm]{images/tree-conf.png}
\center\includegraphics[height=2.5cm]{images/tree-fwm.png}
## Création de l'application #1
Différences entre un projet et une application:
> Une application est une application Web qui fait \
> quelque chose – par exemple un système de blog, \
> une base de données publique ou une application de \
> sondage.\
> Un projet est un ensemble de réglages et d’applications \
> pour un site Web particulier. Un projet peut contenir \
> plusieurs applications.\
> Une application peut apparaître dans plusieurs projets.[^ted]
[^ted]: \tiny https://docs.djangoproject.com/fr/1.11/intro/tutorial01/
## Création de l'application #2
Application de gestions des parefeux.
## Création d'une application
~~~
$ ./manage.py startapp webui
$ pipenv run django-admin startapp garage
~~~
\center\includegraphics[height=3.5cm]{images/tree-webui.png}
\center\includegraphics[height=2.5cm]{images/tree-garage.png}
## Activation de l'application
......@@ -152,23 +131,28 @@ INSTALLED_APPS = [
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'webui',
'garage',
'django_extensions',
]
~~~
## Le fichier de configuration
## Configuration
### conf/settings{\_common,}.py
~~~
$ mv conf/settings.py conf/settings_common.py
$ cat conf/settings.py
from .settings_common import *
### conf/settings.py
~~~python
DEBUG = True
ALLOWED_HOSTS = ['*']
ALLOWED_HOSTS = []
ROOT_URLCONF = 'conf.urls'
LANGUAGE_CODE = 'fr-fr'
TIME_ZONE = 'Europe/Paris'
SECRET_KEY = 'Une_clef_secrete_et_longue!'
$
$ ./manage.py generate_secret_key
~~~
. . .
### Si besoin, pour générer une nouvelle clé
~~~
$ pipenv run ./manage.py generate_secret_key
f#wgrz$@#wh@*x5)_+(*$$^aw(c!q#a4)c0230bwp!iy
~~~
......@@ -178,133 +162,114 @@ f#wgrz$@#wh@*x5)_+(*$$^aw(c!q#a4)c0230bwp!iy
~~~
*.pyc
conf/settings.py
venv/
doc/_build/
*/__pycache__
db.sqlite3*
~~~
## Configuration initiale
### Création des migrations
### Ajout
~~~
$ ./manage.py makemigrations
$ git add .gitignore
~~~
. . .
## Gestion des migrations
### Application des migrations
### Création des migrations (si nécessaire)
~~~
$ ./manage.py migrate
$ pipenv run ./manage.py makemigrations
~~~
. . .
### Création d'un compte admin
### Application des migrations
~~~
$ ./manage.py createsuperuser
$ pipenv run ./manage.py migrate
~~~
## Commandes de base
\center\includegraphics[height=3.5cm]{images/tree-migrate-initial.png}
### Accès au shell
~~~
$ ./manage.py shell
$ # shell avec chargement automatique des classes
$ ./manage.py shell_plus
~~~
# Notre projet
. . .
## Diagramme des classes
### Lancement du serveur de développement
~~~
$ ./manage.py runserver
Performing system checks...
\center\includegraphics[height=4cm]{../vehicules/docs/diagramme_des_classes.png}
System check identified no issues (0 silenced).
September 28, 2017 - 13:29:48
Django version 1.11, using settings 'monsite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
~~~
. . .
Note: pas de clé primaire !
# Modèles
## À vous de jouer !
## Nos classes d'objets
### Documentation
- https://docs.djangoproject.com/fr/ (couche des modèles)
- fichier à modifier: garage/models.py
- faire la classe Garage
- Port
- Service
- Adresse
- Groupe
- Regle
- Modele
- Parefeu
## Port #1
## Lorsque la classe est terminée
### pipenv run ./manage.py makemigrations
~~~
Migrations for 'garage':
garage/migrations/0001_initial.py
- Create model Garage
~~~
### Doit contenir
- protocole: tcp, udp, ...
- début: entier, 0 par défaut
- fin: entier, 0 par défaut
### pipenv run ./manage.py migrate
~~~
Operations to perform:
Apply all migrations: admin, auth, contenttypes, \
garage, sessions
Running migrations:
Applying garage.0001_initial... OK
~~~
. . .
## Fichier de migrations
### webui/models.py
~~~{.py .numberLines}
class Port(models.Model):
protocole = models.CharField(default="any",
max_length=5)
debut = models.PositiveIntegerField(default=0)
fin = models.PositiveIntegerField(default=0)
### garage/migrations/0001_initial.py
~~~python
# [...]
migrations.CreateModel(
name='Garage',
fields=[
('id', models.AutoField(auto_created=True, ...
('nom', models.CharField(max_length=32)),
('adresse', models.CharField(max_length=128, ...
('mail', models.EmailField(max_length=254, ...
('telephone', models.CharField(max_length=12, ...
~~~
## Port #2
### Note
### Remarques
- pas de clé primaire déclarée
Les fichiers de migrations sont à mettre dans le git !
. . .
## Le shell
### Appliquer les modifications
### Accès au shell
~~~
$ ./manage.py makemigrations
$ ./manage.py migrate
$ pipenv run ./manage.py shell
$ # shell avec chargement automatique des classes
$ pipenv run ./manage.py shell_plus
~~~
. . .
### webui/migrations/
~~~
$ ls webui/migrations/
0001_initial.py
0002_auto_20171003_0823.py
~~~
## Port #3
### pipenv run ./manage.py shell_plus
### ./manage.py shell_plus
~~~{.py .numberLines}
>>> p = Port()
>>> p.protocole
'any'
>>> p.debut
0
>>> p.fin
0
>>> p.debut = 22
>>> p.save()
>>> p
<Port: Port object>
>>> # Utiliser la complétion automatique (TAB) !
>>> g = Garage(nom="Mon garage")
>>> g.nom
'Mon garage'
>>> g.save()
>>> g
<Garage: Garage object (1)>
~~~
## Port #4
## Affichage des objets
### Modifier l'affichage
~~~{.py .numberLines}
def __str__(self):
msg = "%d" % self.debut
if self.debut < self.fin:
msg += "-%d" % self.fin
return "%s(%s)" % (msg, self.protocole)
return self.nom
~~~
. . .
......@@ -312,116 +277,62 @@ def __str__(self):
### Résultat
~~~{.py .numberLines}
>>> p = Port()
<Port: 0(any)>
>>> Garage.objects.get(nom="Mon garage")
<Garage: Mon garage>
>>> Garage(nom="Autre").save()
>>> Garage(nom="Zzz", adresse="25 rue toto").save()
>>> Garage.objects.all()
<QuerySet [<Garage: Mon garage>, <Garage: Autre>,
<Garage: Zzz>]>
~~~
## Port #5
### ./manage.py shell_plus
~~~{.py .numberLines}
>>> p = Port(debut=80, protocole="tcp", fin=88)
>>> p
<Port: 80-88(tcp)>
>>> p.save()
>>> p = Port(debut=80, protocole="tcp")
>>> p
<Port: 80(tcp)>
>>> p.save()
>>> Port(protocole="tcp", debut=25).save()
>>> Port.objects.all()
<QuerySet [<Port: 22(any)>, <Port: 80-88(tcp)>,
<Port: 80(tcp)>, <Port: 25(tcp)>]>
~~~
## Port #6
## Trier les instances automatiquement
### Modifier l'ordre d'affichage
~~~{.py .numberLines}
class Port(models.Model):
class Garage(models.Model):
class Meta(object):
ordering = ("debut", "protocole")
ordering = ("nom", "adresse")
~~~
. . .
### ./manage.py shell_plus
### pipenv run ./manage.py shell_plus
~~~{.py .numberLines}
>>> Port.objects.all()
<QuerySet [<Port: 22(any)>, <Port: 25(tcp)>,
<Port: 80(tcp)>, <Port: 80-88(tcp)>]>
>>> Garage.objects.all()
<QuerySet [<Garage: Autre>, <Garage: Mon garage>,
<Garage: Zzz>]>
~~~
## Port #7
### Récupération d'un port
## Manipulation en shell
### pipenv run ./manage.py shell_plus
~~~{.py .numberLines}
>>> Port.objects.get(debut=22)
<Port: 22(any)>
>>> Port.objects.get(debut=80)
...: get() returned more than one Port
>>> grg, flag = Garage.objects\
.get_or_create(nom="L'autre fils")
>>> Garage.objects.filter(nom__contains="Autre")
>>> Garage.objects.filter(nom__icontains="Autre")
>>> Garage.objects.filter(mail__endswith=".fr")\
.filter(adresse__contains="Rouen")
~~~
. . .
### Récupération et création si besoin
~~~{.py .numberLines}
>>> port, flag = Port.objects.get_or_create(debut=25)
~~~
. . .
### Récupération d'une liste de ports
~~~{.py .numberLines}
>>> Port.objects.filter(debut=80)
<QuerySet [<Port: 80(tcp)>, <Port: 80-88(tcp)>]>
>>> Port.objects.filter(debut=80).count()
2
>>> p = Port.objects.filter(debut=80)[1]
>>> p
<Port: 80-88(tcp)>
>>> Garage.objects.get(nom="Zzz").delete()
>>> Garage.objects.all().delete()
~~~
## Port #8
## À vous de jouer #2
### Faire dans l'ordre les classes
### ./manage.py shell_plus
~~~{.py .numberLines}
>>> Port.objects.filter(debut__gt=20)
<QuerySet [<Port: 22(any)>, <Port: 25(tcp)>,
<Port: 80(tcp)>]>
>>> Port.objects.filter(debut__gt=20)\
.filter(debut__lte=25)
<QuerySet [<Port: 22(any)>, <Port: 25(tcp)>]>
>>> Port.objects.filter(debut__gt=20, debut__lte=25)
<QuerySet [<Port: 22(any)>, <Port: 25(tcp)>]>
~~~
- Vehicule
- AFaire
- Entretien
## Port #9
### Suppression
### Documentation
~~~{.py .numberLines}
>>> Port.objects.get(id=2).delete()
(1, {'webui.Service_ports': 0, 'webui.Port': 1})
>>> Port.objects.filter(debut__gt=22,
debut__lte=25).delete()
(1, {'webui.Service_ports': 0, 'webui.Port': 1})
>>> Port.objects.all().delete()
~~~
## À faire
### https://docs.djangoproject.com/fr/
- Adresse
- nom: chaine de caractères (25)
- ip: une adresse IP
- masque: le masque réseau (défaut: 32)
- Groupe
- nom: chaine de caractères (25)
- adresses: une liste d'Adresse
- Service
- nom: chaine de caractères (25)
- ports: une liste de ports
- https://docs.djangoproject.com/fr/
- fichier à modifier: garage/models.py
% Django par la pratique #02
% Sébastien Bonnegent
% version 17.10.22
% version 2018
# Interface d'administration
## Prérequis
### garage/models.py
- Garage
- Vehicule
- AFaire
- Entretien
## Développement
### Lancement du serveur de développement
~~~
$ pipenv run ./manage.py runserver
Performing system checks...
System check identified no issues (0 silenced).
September 28, 2017 - 13:29:48
Django version 1.11, using settings 'monsite.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
~~~
## Consultation
### Adresse
- http://localhost:8000/
- http://localhost:8000/admin/
### Création d'un compte administrateur
~~~
$ pipenv run ./manage.py createsuperuser
~~~
## Ajout de nos classes
### garage/admin.py
~~~python
from .models import Garage, Vehicule, AFaire, Entretien
admin.site.register(Garage)
admin.site.register(Vehicule)
admin.site.register(AFaire)
admin.site.register(Entretien)
~~~
### http://localhost:8000/admin/
- rafraichir l'affichage
- créer des objets dans les différentes classes
## Personnalisation
### garage/admin.py
~~~python
class EntretienAdmin(admin.ModelAdmin):
list_display = ('vehicule', 'kms', 'date', 'montant')
date_hierarchy = 'date'
# ordering = ['date'] >> class Meta
search_fields = ['vehicule__marque',
'vehicule__modele']
admin.site.register(Entretien, EntretienAdmin)