Notes du 2018-07-01
2020-09-06: Add django-multiselectfield

Construire un form Django

form.py

On crée un fichier forms.py à la racine de l'appli :

from django import forms
 
class TestForm(forms.Form):
    CITIES_CHOICES = (
        (0, 'Paris'),
        (1, 'Toulouse'),
        (2, 'Lyon'),
    )
    name = forms.CharField(label='Your name', max_length=50)
    email = forms.EmailField(label='Your email', max_length=50, required=False)
    yes_no = forms.BooleanField(label='Either Yes or No')
    city = forms.ChoiceField(label='Your city', choices=CITIES_CHOICES)

Coté HTML: templates/appone/form.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Testing Form</title>
</head>
<body>
    <h1>Test form</h1>
    <form action="" method="post">
        {% csrf_token %}
        <table>
            {{ form.as_table }}
        </table>
        <input type="submit" value="Submit">
    </form>
</body>
</html>

Coté views.py

from appone.forms import TestForm
 
def get_form_data(request):
    form = TestForm()
    return render(request, 'appone/form.html', {'form': form})

Coté urls.py

    path('getformdata/', views.get_form_data),

Screen

Traiter la requête d'un form

Mettre l'url dans l'action du formulaire.

Coté URL

urlpatterns = [
    [..]
    path('getformdata/', views.get_form_data, name='get-form-data'),
    [..]
]

Coté HTML

on ajoute “{# url get-form-data #}“ dans l'action du formulaire.

[..]
    <form action="{# url get-form-data #}" method="post">
        {% csrf_token %}
        <table>
            {{ form.as_table }}
        </table>
        <input type="submit" value="Submit">
    </form>
[..]

Le traitement: views.py

On doit séparer le traitement POST de l'affichage:

from appone.forms import TestForm
 
def get_form_data(request):
    # permet de séparer le <traitement> de <l'affichage>
    # -> traitement du formulaire
    if request.method == 'POST':
        print('In POST processing')
        form = TestForm(request.POST)
        if form.is_valid():
            print('name:', form.cleaned_data['name'])
            print('email:', form.cleaned_data['email'])
            print('yes_no:', form.cleaned_data['yes_no'])
            print('city:', form.cleaned_data['city'])
    # -> affichage de la page
    else:
        form = TestForm()
    return render(request, 'appone/form.html', {'form': form})

Redirection suite à formulaire

Coté views.py

On crée une fonction qui s'affichera après la redirection, elle même appelée par la partie traitement du formulaire :

from appone.forms import TestForm
from django.http import HttpResponseRedirect
from django.urls import reverse
 
def thanks(request):
    return HttpResponse('Thanks, your form as been processed')
 
def get_form_data(request):
    # permet de séparer le <traitement> de <l'affichage>
    # -> traitement du formulaire
    if request.method == 'POST':
        print('In POST processing')
        form = TestForm(request.POST)
        if form.is_valid():
            print('name:', form.cleaned_data['name'])
            print('email:', form.cleaned_data['email'])
            print('yes_no:', form.cleaned_data['yes_no'])
            print('city:', form.cleaned_data['city'])
            # redirection
            return HttpResponseRedirect(reverse('thanks'))
    # -> affichage de la page
    else:
        form = TestForm()
    return render(request, 'appone/form.html', {'form': form})

Coté URL

On utilise l'url nommée :

urlpatterns = [
    [..]
    path('getformdata/', views.get_form_data, name='get-form-data'),
    path('thanks/', views.thanks, name='thanks'),
    [..]

A la validation du formulaire s'affiche :

Thanks, your form as been processed

Package: django-multiselectfield

Permet de transformer un CHOICE_FIELD en plusieurs case à cocher.
Source: https://pypi.org/project/django-multiselectfield/
Vidéo: https://www.youtube.com/watch?v=5jWJBpS0tkg