Commit 715d8783 authored by Bonnegent Sebastien's avatar Bonnegent Sebastien
Browse files

cours 4 ok

parent bb7b01f1
all: cours1.html cours2.html cours3.html
all: cours1.html cours2.html cours3.html cours4.html
%.html: %.md
pandoc -s -t revealjs -V revealjs-url=./reveal.js -V theme=beige -o $@ $<
......@@ -9,40 +9,45 @@ séance.
# Plan
## Cours 1
* mise en place du projet
* mise en place de l'application
* migration
* 1er modèle (Port)
* shell
- mise en place du projet
- mise en place de l'application
- migration
- 1er modèle (Port)
- shell
## Cours 2
* interface d'administration
* modèles avec relations (Service, Groupe)
- interface d'administration
- modèles avec relations (Service, Groupe)
## Cours 3
* suite des modèles avec relations (Regle, Parefeu)
* 1er page web
- suite des modèles avec relations (Regle, Parefeu)
- 1er page web
## Cours 4
* logging
* messages
* frontend: manipulation des objets
* script des gestions
- rappel sur les fichiers
- authentification, limitation d'accès
- vue liste générique (Parefeu)
- vue détail générique (Parefeu)
- formulaire simple (contact)
## Cours 5
* template générique
* formulaire
* envoi de mails
* hijack et restrictions d'accès
- frontend: manipulation des objets
- script des gestions
- logging
- messages
- template générique
- formulaire
- envoi de mails
- hijack et restrictions d'accès
## Cours 6
* utilisation de black
* tests
- utilisation de black
- tests
## Cours 7
* QCM
* API Rest
* utilisation de docker
- QCM
- API Rest
- utilisation de docker
# Comment démarrer ?
~~~
......@@ -54,13 +59,13 @@ Il faut ouvrir le fichier **cours1.html** dans votre navigateur favori.
# Liste des fichiers
* cours?.html : le support de cours
* cours?.md : la source du support de cours
* fwm? : le répertoire du projet django correspondant au cours
* make : regénère les fichiers html
- cours?.html : le support de cours
- cours?.md : la source du support de cours
- fwm? : le répertoire du projet django correspondant au cours
- make : regénère les fichiers html
# Outils utilisés
* vim
* pandoc
* revealjs
- vim
- pandoc
- revealjs
This diff is collapsed.
---
author:
- Sébastien Bonnegent
title: Django par la pratique 4/7
---
# Départ
## Support
- cours4.html
## Préparation
### L'ancien
~~~
$ cd fwm3
$ pipenv --rm
~~~
### Le nouveau
~~~
$ cd fwm4
$ pipenv install
~~~
## Au programme
- rappel sur les fichiers
- authentification, limitation d'accès
- vue liste générique (Parefeu)
- vue détail générique (Parefeu)
- envoi de mails
- formulaire simple (contact)
- messages
# Rappel
## Rôle de chaque fichier
* ./manage.py: contrôles et commandes
* ./db.sqlite3: base de données
* Pipfile: dépendances primaires
* Pipfile.lock: toutes les dépendances
## Rôle de chaque fichier
* conf/settings.py: configuration
* conf/urls.py: routage des URI
* conf/wsgi.py: pour la production
## Rôle de chaque fichier
* webui/views.py: manipulations des objets
* webui/forms.py: formulaires
* webui/admin.py: administration
* webui/templates/: préparation de l'affichage
* webui/migrations/: évolution de la BD
* webui/tests.py: les tests
* webui/models.py: les modèles
# Authentification
## à modifier
### webui/templates/webui/home.html
~~~
{% if user.is_authenticated %}
...
{% if user.is_staff %}
...
{% endif %}
{% endif %}
~~~
### conf/urls.py
~~~python
from django.contrib.auth.decorators import login_required
# ...
path('accounts/', include('django.contrib.auth.urls')),
# ...
~~~
## à modifier
### conf/settings.py
~~~python
LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL = '/'
~~~
## à modifier
### webui/templates/registration/login.html
- le template doit être présent
### conf/urls.py
~~~python
path('', login_required(views.home_v2), name='home'),
~~~
# Vue liste générique
## Parefeu
### Documentation
https://docs.djangoproject.com/fr/2.2/topics/class-based-views/generic-display/
## Implémentation
### webui/views.py
~~~python
from django.views.generic import ListView
from webui.models import Parefeu
class ParefeuList(ListView):
model = Parefeu
~~~
## Templates
### webui/templates/webui/parefeu_list.html
~~~python
{% extends "webui/home.html" %}
{% block content %}
<h2>Parefeux</h2>
<ul>
{% for parefeu in object_list %}
<li>{{ parefeu.nom }}</li>
{% endfor %}
</ul>
{% endblock %}
~~~
## Routage
### conf/urls.py
~~~python
...
path('parefeu/',
login_required(views.ParefeuList.as_view()),
name='parefeux'),
...
~~~
## Templates
### webui/templates/webui/home.html
~~~python
<li class="nav-item active">
<a class="nav-link" href="{% url 'parefeux' %}">Parefeux</a>
</li>
~~~
## Menu actif
### webui/templates/webui/home.html
~~~python
...
<li class="nav-item active">
... # devient
<li class="nav-item {{ menu_parefeu }}"
~~~
## Implémentation
### webui/views.py
~~~python
class ParefeuList(ListView):
model = Parefeu
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['menu_parefeu'] = 'active'
return context
~~~
# Vue détail générique
## Parefeu
### webui/views.py
~~~python
from django.views.generic import DetailView
class ParefeuDetail(DetailView):
context_object_name = 'parefeu'
model = Parefeu
# queryset = Parefeu.objects.all()
~~~
## Routage
### conf/urls.py
~~~python
path('parefeu/<int:pk>/',
login_required(views.ParefeuDetail.as_view()),
name='parefeu-detail'),
~~~
## Templates
### webui/templates/webui/parefeu_detail.html
~~~python
{% extends "webui/home.html" %}
{% block title %}Parefeu: {{parefeu.nom}}{% endblock %}
{% block content %}
<h2>{{parefeu.nom}}</h2>
<table class="table table-striped">
<tr>
<th>Nombre de règles total</th>
<td>{{parefeu.nombre_de_regles}}</td>
</tr>
<tr>
<th>Administrateur</th>
<td>{{parefeu.admin}}</td>
</tr>
<tr>
<th>Dernière modification</th>
<td>{{parefeu.modification}}</td>
</tr>
{% if parefeu.parefeu_set.count %}
<tr>
<th>Parefeu(x) utilisant ce parefeu comme modèle</th>
<td>{% for fw in parefeu.parefeu_set.all %}
<a href="{% url 'parefeu' fw.id %}">{{fw}}</a>
{% endfor %}
</td>
</tr>
{% endif %}
</table>
{% endblock %}
~~~
## Accés facile
### webui/templates/webui/parefeu_list.html
~~~python
<li><a href="{% url 'parefeu-detail' parefeu.id %}">
{{ parefeu.nom }}</a></li>
~~~
## Menu active
### webui/views.py
~~~python
def get_context_data(self, **kwargs):
context = super().get_context_data(**kwargs)
context['menu_parefeu'] = 'active'
return context
~~~
## à faire
* ServiceList
* PortList
# Mail
## Envoi de mails
### Documentation
* https://docs.djangoproject.com/fr/2.2/topics/email/
* en production, envoi des messages d'erreurs
* différents des Users 'superadmins'
## Envoi de mails
### conf/settings.py
~~~python
ADMINS = [('Admin', 'ad@min.fr'), ]
EMAIL_HOST = "127.0.0.1"
EMAIL_PORT = 2525
SERVER_EMAIL = 'noreply@insa-rouen.fr'
~~~
### un faux serveur smtp
~~~
$ pipenv run ./manage.py help mail_debug
$ pipenv run ./manage.py mail_debug --use-settings
~~~
# Formulaire simple
## Formulaire de contact
* contrôler la partie la liste des services
* bouton sur les pages listes des services et des ports
* pouvoir demander la création de service/port aux admins
* https://docs.djangoproject.com/fr/2.2/topics/class-based-views/generic-editing/
## Suivre la documentation
### à modifier
* webui/forms.py
* webui/views.py
* webui/templates/webui/contact.html
* conf/urls.py
# Messages
## Pourquoi ?
* affichage facile à l'utilisateur
* permet un retour sur les opérations
* fourni par Django
## Mise en place
### webui/views.py
~~~python
from django.contrib import messages
class ContactView(FormView):
...
def form_valid(self, form):
if form.send_email():
messages.success(self.request, "La demande a été transmise")
else:
messages.warning(self.request, "La demande n'a pu être transmise")
return super().form_valid(form)
~~~
## Mise en place
### webui/templates/webui/home.html
~~~
{% for message in messages %}
{% if message.tags == "error" %}
<div class="alert alert-danger" role="alert">
{% else %}
<div class="alert alert-{{ message.tags }}" role="alert">
{% endif %}
{{ message }}</div>
{% endfor %}
~~~
# FIN !
No preview for this file type
......@@ -18,7 +18,7 @@
<ul class="navbar-nav mr-auto">
{% if user.is_staff %}
<li class="nav-item">
<a class="nav-link" href="#">Admin</a>
<a class="nav-link" href="/admin">Admin</a>
</li>
{% endif %}
<li class="nav-item active">
......
[[source]]
name = "pypi"
url = "https://pypi.org/simple"
verify_ssl = true
[dev-packages]
[packages]
django = "*"
django-extensions = "*"
ipython = "*"
django-bootstrap-static = "*"
fontawesome = "*"
[requires]
python_version = "3.6"
{
"_meta": {
"hash": {
"sha256": "5eaa1b0486397527fe82e874288132e34a53a04d2cc347a3af9edd36ac6d4122"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.6"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"backcall": {
"hashes": [
"sha256:38ecd85be2c1e78f77fd91700c76e14667dc21e2713b63876c0eb901196e01e4",
"sha256:bbbf4b1e5cd2bdb08f915895b51081c041bac22394fdfcfdfbe9f14b77c08bf2"
],
"version": "==0.1.0"
},
"decorator": {
"hashes": [
"sha256:54c38050039232e1db4ad7375cfce6748d7b41c29e95a081c8a6d2c30364a2ce",
"sha256:5d19b92a3c8f7f101c8dd86afd86b0f061a8ce4540ab8cd401fa2542756bce6d"
],
"version": "==4.4.1"
},
"django": {
"hashes": [
"sha256:16040e1288c6c9f68c6da2fe75ebde83c0a158f6f5d54f4c5177b0c1478c5b86",
"sha256:89c2007ca4fa5b351a51a279eccff298520783b713bf28efb89dfb81c80ea49b"
],
"index": "pypi",
"version": "==2.2.7"
},
"django-bootstrap-static": {
"hashes": [
"sha256:d9f1f9f7561efb9a73cd80a380d26628047805540ddb12002a453cebb6a74fed",
"sha256:fb8516189604b783f24a76e582ccbd90254ba81499dcf01e04e9016666760e8c"
],
"index": "pypi",
"version": "==4.2.1"
},
"django-extensions": {
"hashes": [
"sha256:a9db7c56a556d244184f589f2437b4228de86ee45e5ebb837fb20c6d54e95ea5",
"sha256:b58320d3fe3d6ae7d1d8e38959713fa92272f4921e662d689058d942a5b444f7"
],
"index": "pypi",
"version": "==2.2.5"
},
"fontawesome": {
"hashes": [
"sha256:1b5e8f2ed12a74b88aef6f404ff770af425324041bc5620523a802d5406595b8",
"sha256:642d74da5f4726bb2c8f035a2f4a98fdc4294d213a291994ee0b3d845166f9e8"
],
"index": "pypi",
"version": "==5.10.1.post1"
},
"ipython": {
"hashes": [
"sha256:dfd303b270b7b5232b3d08bd30ec6fd685d8a58cabd54055e3d69d8f029f7280",
"sha256:ed7ebe1cba899c1c3ccad6f7f1c2d2369464cc77dba8eebc65e2043e19cda995"
],
"index": "pypi",
"version": "==7.9.0"
},
"ipython-genutils": {
"hashes": [
"sha256:72dd37233799e619666c9f639a9da83c34013a73e8bbc79a7a6348d93c61fab8",
"sha256:eb2e116e75ecef9d4d228fdc66af54269afa26ab4463042e33785b887c628ba8"
],
"version": "==0.2.0"
},
"jedi": {
"hashes": [
"sha256:786b6c3d80e2f06fd77162a07fed81b8baa22dde5d62896a790a331d6ac21a27",
"sha256:ba859c74fa3c966a22f2aeebe1b74ee27e2a462f56d3f5f7ca4a59af61bfe42e"
],
"version": "==0.15.1"
},
"parso": {
"hashes": [
"sha256:63854233e1fadb5da97f2744b6b24346d2750b85965e7e399bec1620232797dc",
"sha256:666b0ee4a7a1220f65d367617f2cd3ffddff3e205f3f16a0284df30e774c2a9c"
],
"version": "==0.5.1"
},
"pexpect": {
"hashes": [
"sha256:2094eefdfcf37a1fdbfb9aa090862c1a4878e5c7e0e7e7088bdb511c558e5cd1",
"sha256:9e2c1fd0e6ee3a49b28f95d4b33bc389c89b20af6a1255906e90ff1262ce62eb"
],
"markers": "sys_platform != 'win32'",
"version": "==4.7.0"
},
"pickleshare": {
"hashes": [
"sha256:87683d47965c1da65cdacaf31c8441d12b8044cdec9aca500cd78fc2c683afca",
"sha256:9649af414d74d4df115d5d718f82acb59c9d418196b7b4290ed47a12ce62df56"
],
"version": "==0.7.5"
},
"prompt-toolkit": {
"hashes": [
"sha256:46642344ce457641f28fc9d1c9ca939b63dadf8df128b86f1b9860e59c73a5e4",
"sha256:e7f8af9e3d70f514373bf41aa51bc33af12a6db3f71461ea47fea985defb2c31",
"sha256:f15af68f66e664eaa559d4ac8a928111eebd5feda0c11738b5998045224829db"
],
"version": "==2.0.10"
},
"ptyprocess": {
"hashes": [
"sha256:923f299cc5ad920c68f2bc0bc98b75b9f838b93b599941a6b63ddbc2476394c0",
"sha256:d7cc528d76e76342423ca640335bd3633420dc1366f258cb31d05e865ef5ca1f"
],
"version": "==0.6.0"
},
"pygments": {
"hashes": [
"sha256:71e430bc85c88a430f000ac1d9b331d2407f681d6f6aec95e8bcfbc3df5b0127",
"sha256:881c4c157e45f30af185c1ffe8d549d48ac9127433f2c380c24b84572ad66297"
],
"version": "==2.4.2"
},
"pytz": {
"hashes": [
"sha256:1c557d7d0e871de1f5ccd5833f60fb2550652da6be2693c1e02300743d21500d",
"sha256:b02c06db6cf09c12dd25137e563b31700d3b80fcc4ad23abb7a315f2789819be"
],
"version": "==2019.3"
},
"six": {
"hashes": [
"sha256:1f1b7d42e254082a9db6279deae68afb421ceba6158efa6131de7b3003ee93fd",
"sha256:30f610279e8b2578cab6db20741130331735c781b56053c59c4076da27f06b66"
],
"version": "==1.13.0"
},
"sqlparse": {
"hashes": [
"sha256:40afe6b8d4b1117e7dff5504d7a8ce07d9a1b15aeeade8a2d10f130a834f8177",
"sha256:7c3dca29c022744e95b547e867cee89f4fce4373f3549ccd8797d8eb52cdb873"
],
"version": "==0.3.0"
},
"traitlets": {
"hashes": [
"sha256:70b4c6a1d9019d7b4f6846832288f86998aa3b9207c6821f3578a6a6a467fe44",
"sha256:d023ee369ddd2763310e4c3eae1ff649689440d4ae59d7485eb4cfbbe3e359f7"
],
"version": "==4.3.3"
},
"wcwidth": {
"hashes": [
"sha256:3df37372226d6e63e1b1e1eda15c594bca98a22d33a23832a90998faa96bc65e",
"sha256:f4ebe71925af7b40a864553f761ed559b43544f8f71746c2d756c7fe788ade7c"
],
"version": "==0.1.7"
}
},
"develop": {}
}
"""
Django settings for conf project.
Generated by 'django-admin startproject' using Django 2.2.6.
For more information on this file, see
https://docs.djangoproject.com/en/2.2/topics/settings/
For the full list of settings and their values, see
https://docs.djangoproject.com/en/2.2/ref/settings/
"""
import os
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
ADMINS = [('Admin', 'ad@min.fr'), ]
EMAIL_HOST = "127.0.0.1"
EMAIL_PORT = 2525
SERVER_EMAIL = 'noreply@insa-rouen.fr'
# Quick-start development settings - unsuitable for production
# See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/
# SECURITY WARNING: keep the secret key used in production secret!
SECRET_KEY = 'ldo+99!dbim5qy+es_y(vj6%1+-j5n4lwaops3ovy=rmt&#b1_'
# SECURITY WARNING: don't run with debug turned on in production!
DEBUG = True
ALLOWED_HOSTS = []
LOGOUT_REDIRECT_URL = '/'
LOGIN_REDIRECT_URL = '/'
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',