Comment personnaliser le rendu de ses formulaires Django avec django-crispy-form ?

 

WePynaire

(version simplifiée)

Objectifs

  • Découvrir django-crispy-forms
  • Approfondir la mise en forme des formulaires
  • Séparer le form et la forme

Liens utiles

Le dépôt du WePynaire:  https://bit.ly/wepynaire-20230130 

Diapositives du WePynaire: http://bit.ly/3DxbC7r

$ mkdir .venv
$ pipenv install django
$ pipenv run django-admin startproject config .
$ pipenv run python manage.py startapp wepynaire

Création du projet

Configuration du projet

Configuration du répertoire des templates

Création d'un base.html

Configuration selon le Quick start de Bootstrap 5.2

Le code de base est directement copié du Quick start de Bootstrap 5.2

Le base.html du Quick start est adapté pour Django

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Adaptation de la langue

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Création d'un bloc de titre

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Création d'un bloc pour le CSS

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Création d'un bloc pour les scripts dans l'en-tête

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Création d'un bloc pour les classes de body

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Création d'un bloc pour la barre de navigation

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Création d'un bloc pour le contenu principal

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Création d'un bloc pour le pied de page

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Création d'un bloc pour les scripts de bas de page

<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>{% block title %}WePynaire | PlacePython{% endblock title %}</title>

    {% block head_styles %}
    <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/css/bootstrap.min.css" 
        rel="stylesheet" 
        integrity="sha384-rbsA2VBKQhggwzxH7pPCaAqO46MgnOM80zW1RWuH61DGLwZJEdK2Kadq2F9CUG65" 
        crossorigin="anonymous"
    >
    {% endblock head_styles %}
    
    {% block head_scripts %}{% endblock head_scripts %}
  </head>
  <body classes="{% block body_classes %}{% endblock body_classes %}">
    
    {% block nav %}{% endblock nav %}

    {% block content %}{% endblock content %}

    {% block footer %}{% endblock footer %}

    {% block bottom_scripts %}
    <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.3/dist/js/bootstrap.bundle.min.js" 
        integrity="sha384-kenU1KFdBIe4zVF0s0G1M5b4hcpxyD9F7jL+jjXkk+Q2h455rYXK/7HAuoJl+0I4" 
        crossorigin="anonymous"
    ></script>
    {% endblock bottom_scripts %}
  </body>
</html>

Créaction des modèles

from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
  """Exemple d'utilisateur."""

  
class UserAddress(models.Model):
  """Modèle de liaison entre utilisateur et adresse."""


class Address(models.Model):
  """Représente une adresse postale."""
  
from django.db import models
from django.conf import settings
from django.contrib.auth.models import AbstractUser


class User(AbstractUser):
    """Exemple d'utilisateur."""

    first_name = None
    last_name = None
    name = models.CharField(max_length=255, blank=True)
    addresses = models.ManyToManyField(
        "Address",
        related_name="users",
        through="UserAddress",
    )


class UserAddress(models.Model):
    """Modèle de liaison entre utilisateur et adresse."""

    class AdresseRoles(models.TextChoices):
        HOME = "home", "Adresse de domicile"
        INVOICE = "invoice", "Adresse de facturation"
        DELIVERY = "delivery", "Adresse de livraison principale"

    user = models.ForeignKey(
        settings.AUTH_USER_MODEL, on_delete=models.CASCADE
    )
    address = models.ForeignKey("Address", on_delete=models.CASCADE)
    address_role = models.CharField(
        "role de l'adresse",
        max_length=255,
        choices=AdresseRoles.choices,
        default=AdresseRoles.HOME,
    )
    created = models.DateTimeField(
      "date de création", auto_now_add=True
    )
    updated = models.DateTimeField(
      "date de mise à jour", auto_now=True
    )


class Address(models.Models):
    """Représente une adresse postale."""

    class Countries(models.TextChoices):
        SWITZERLAND = "CH", "Suisse"
        FRANCE = "F", "France"
        BELGIUM = "B", "Belgique"
        CANADA = "CAN", "Canada"

    street = models.CharField("rue", max_length=255, blank=True)
    street_number = models.CharField(
        "numéro de la rue", max_length=6, blank=True
    )
    address_complement = models.CharField(
        "complément d'adresse", max_length=255, blank=True
    )
    city = models.CharField("ville", max_length=100)
    zip_code = models.CharField("numéro postal", max_length=6)
    country = models.CharField(
        "pays",
        max_length=4,
        choices=Countries.choices,
        default=Countries.SWITZERLAND,
    )
$ python manage.py makemigrations
$ python manage.py migrate
$ python manage.py makemigrations
$ python manage.py migrate

Créaction des formulaires

from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    address_type = forms.ChoiceField(label="type de l'adresse")

    class Meta:
        model = Address
        fields = (
            "street",
            "street_number",
            "address_complement",
            "city",
            "zip_code",
            "country",
        )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

Pour UserAddress

La HomeView

...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

le template home.html

$ python manage.py runserver

Installation de django-crispy-forms pour Bootstrap 5

1. Visiter la documentation de crispy-bootstrap5

2. Installer crispy-bootstrap5

$ pipenv install crispy-bootstrap5

3. Enregistrer les crispy-forms et crispy-bootstrap5 dans INSTALLED_APPS

4. Définir les constantes de config de crispy-forms

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
<div class="container">
    <h1 class="row">Nouvelle inscription</h1>
    <form method="post" class="row">
        {% csrf_token %}
        {% for form in forms %}
            {{ form|crispy }}
        {% endfor %}
        <button type="submit" class="btn btn-primary">Soumettre</button>
    </form>
</div>
{% endblock content %}

home.html

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
<div class="container">
    <h1 class="row">Nouvelle inscription</h1>
    <form method="post" class="row">
        {% csrf_token %}
        {% for form in forms %}
            {{ form|crispy }}
        {% endfor %}
        <button type="submit" class="btn btn-primary">Soumettre</button>
    </form>
</div>
{% endblock content %}

home.html

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
<div class="container">
    <h1 class="row">Nouvelle inscription</h1>
    <form method="post" class="row">
        {% csrf_token %}
        {% for form in forms %}
            {{ form|crispy }}
        {% endfor %}
        <button type="submit" class="btn btn-primary">Soumettre</button>
    </form>
</div>
{% endblock content %}

home.html

  • L'ordre des champs est imposé
  • La mise en page est automatique mais rigide

Simple mais pas très flexible

Regardons plus loin !

Crispy FormHelper & Layouts

Lisons un peu de documentation

1. Instancier un FormHelper

2. Créer une mise en page (layout)

Instancions les FormHelper

from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""


    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    address_type = forms.ChoiceField(label="Type de l'adresse")

    class Meta:
        model = Address
        fields = (
            ...
        )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "street",
            "street_number",
            "address_complement",
            "city",
            "zip_code",
            "country",
        )


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    address_type = forms.ChoiceField(label="Type de l'adresse")

    class Meta:
        model = Address
        fields = (
            ...
        )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "street",
            "street_number",
            "address_complement",
            "city",
            "zip_code",
            "country",
        )


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    address_type = forms.ChoiceField(label="Type de l'adresse")

    class Meta:
        model = Address
        fields = (
            ...
        )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "street",
            "street_number",
            "address_complement",
            "city",
            "zip_code",
            "country",
        )


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    address_type = forms.ChoiceField(label="Type de l'adresse")

    class Meta:
        model = Address
        fields = (
            ...
        )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "street",
            "street_number",
            "address_complement",
            "city",
            "zip_code",
            "country",
        )


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
from django import forms
from django.contrib.auth import get_user_model
from django.contrib.auth import forms as auth_forms

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Div, Row, Column

from .models import UserAddress, Address

User = get_user_model()


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "name",
            "username",
            "password1",
            "password2",
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    address_type = forms.ChoiceField(label="Type de l'adresse")

    class Meta:
        model = Address
        fields = (
            ...
        )

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            "street",
            "street_number",
            "address_complement",
            "city",
            "zip_code",
            "country",
        )


    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
   
  
  
  
  
  
{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block content %}
<div class="container">
    <h1 class="row">Nouvelle inscription</h1>
    <form method="post" class="row">
        {% csrf_token %}
        {% for form in forms %}
            {% crispy form %}
        {% endfor %}
        <button 
            type="submit" 
            class="btn btn-primary"
        >Soumettre</button>
    </form>
</div>
{% endblock content %}

Personnalisons un peu ce formulaire

...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="border: 1px black solid; border-radius: 10px; margin-bottom: 1rem;",
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="border: 1px black solid; border-radius: 10px; margin-bottom: 1rem;",
            ),
        )
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="border: 1px black solid; border-radius: 10px; margin-bottom: 1rem;",
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="border: 1px black solid; border-radius: 10px; margin-bottom: 1rem;",
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column("name"),
                    Column("username"),
                ),
                Row(
                    Column("password1"),
                    Column("password2"),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

La mise en page est OK ! 

Personnalisons les champs eux-même p.ex. en modifiant le placeholder

placeholder personnalisé

...

from crispy_forms.helper import FormHelper
from crispy_forms.layout import Layout, Row, Column, Fieldset

...


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.help_text_inline = False
        self.helper.layout = Layout(
            Fieldset(
                "Données de connexion",
                Row(
                    Column(Field("name", placeholder="Votre nom")),
                    Column(Field("username", placeholder="Votre username")),
                ),
                Row(
                    Column(
                        Field("password1", placeholder="Votre mot de passe")
                    ),
                    Column(
                        Field(
                            "password2", placeholder="Répétez le mot de passe"
                        )
                    ),
                ),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = Layout(
            Fieldset(
                "Adresse",
                Row(
                    Column("street", css_class="col-md-10"),
                    Column("street_number", css_class="col-md-2"),
                ),
                Row("address_complement"),
                Row(
                    Column("zip_code", css_class="col-md-4"),
                    Column("city"),
                ),
                Row("country"),
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )

        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

from crispy_forms.layout import Field

Field(
    "nom du champ",

    css_id="ma-classe",

    hx_get="valeur de hx-get",

    attr2="valeur de attr2

)

Les classes de Layout (Field, Row, Column, Div, Button, etc.) peuvent recevoir des paramètres qui deviendront des attributs HTML

  • css_id devient id
  • css_class devient class

  • placeholder devient placeholder

  • hx_get devient hx-get

  • hx_target devient hx-target

  • ...

  • css_id devient id
  • css_class devient class

  • placeholder devient placeholder

  • hx_get devient hx-get

  • hx_target devient hx-target

  • ...

  • css_id devient id
  • css_class devient class

  • placeholder devient placeholder

  • hx_get devient hx-get

  • hx_target devient hx-target

  • ...

  • css_id devient id
  • css_class devient class

  • placeholder devient placeholder

  • hx_get devient hx-get

  • hx_target devient hx-target

  • ...

  • css_id devient id
  • css_class devient class

  • placeholder devient placeholder

  • hx_get devient hx-get

  • hx_target devient hx-target

  • ...

  • css_id devient id
  • css_class devient class

  • placeholder devient placeholder

  • hx_get devient hx-get

  • hx_target devient hx-target

  • ...

Séparer la structure du formulaire et sa mise en page

  • form_layouts.py: mise en forme des formulaires
  • forms.py: définition des formulaires

Analysons notre form_layouts.py

class UserCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'utisateur."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Données de connexion",
                Row(
                    Column(Field("name", placeholder="Votre nom")),
                    Column(Field("username", placeholder="Votre username")),
                ),
                Row(
                    Column(
                        Field("password1", placeholder="Votre mot de passe")
                    ),
                    Column(
                        Field(
                            "password2", placeholder="Répétez le mot de passe"
                        )
                    ),
                ),
                # Utilisez des classes css pour le style
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'adresse."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Adresse",
                Row(
                    Column(
                        Field("street", placeholder="Votre rue"),
                        css_class="col-md-10",
                    ),
                    Column(
                        Field("street_number", placeholder="N°"),
                        css_class="col-md-2",
                    ),
                ),
                Row(
                    Field(
                        "address_complement",
                        placeholder="Votre complément d'adresse",
                    ),
                ),
                Row(
                    Column(
                        Field("zip_code", placeholder="Code postal"),
                        css_class="col-md-4",
                    ),
                    Column(Field("city", placeholder="Votre ville")),
                ),
                Row("country", placeholder="Votre pays"),
                # Utilisez des classes css pour le style
                style="""
                        border: 1px black solid; 
                        border-radius: 10px; 
                        margin-bottom: 1rem;
                    """,
            ),
        )
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

class UserCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'utisateur."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Données de connexion",
                Row(
                    Column(Field("name", placeholder="Votre nom")),
                    Column(Field("username", placeholder="Votre username")),
                ),
                Row(
                    Column(
                        Field("password1", placeholder="Votre mot de passe")
                    ),
                    Column(
                        Field(
                            "password2", placeholder="Répétez le mot de passe"
                        )
                    ),
                ),
                # Utilisez des classes css pour le style
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'adresse."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Adresse",
                Row(
                    Column(
                        Field("street", placeholder="Votre rue"),
                        css_class="col-md-10",
                    ),
                    Column(
                        Field("street_number", placeholder="N°"),
                        css_class="col-md-2",
                    ),
                ),
                Row(
                    Field(
                        "address_complement",
                        placeholder="Votre complément d'adresse",
                    ),
                ),
                Row(
                    Column(
                        Field("zip_code", placeholder="Code postal"),
                        css_class="col-md-4",
                    ),
                    Column(Field("city", placeholder="Votre ville")),
                ),
                Row("country", placeholder="Votre pays"),
                # Utilisez des classes css pour le style
                style="""
                        border: 1px black solid; 
                        border-radius: 10px; 
                        margin-bottom: 1rem;
                    """,
            ),
        )
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

class UserCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'utisateur."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Données de connexion",
                Row(
                    Column(Field("name", placeholder="Votre nom")),
                    Column(Field("username", placeholder="Votre username")),
                ),
                Row(
                    Column(
                        Field("password1", placeholder="Votre mot de passe")
                    ),
                    Column(
                        Field(
                            "password2", placeholder="Répétez le mot de passe"
                        )
                    ),
                ),
                # Utilisez des classes css pour le style
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'adresse."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Adresse",
                Row(
                    Column(
                        Field("street", placeholder="Votre rue"),
                        css_class="col-md-10",
                    ),
                    Column(
                        Field("street_number", placeholder="N°"),
                        css_class="col-md-2",
                    ),
                ),
                Row(
                    Field(
                        "address_complement",
                        placeholder="Votre complément d'adresse",
                    ),
                ),
                Row(
                    Column(
                        Field("zip_code", placeholder="Code postal"),
                        css_class="col-md-4",
                    ),
                    Column(Field("city", placeholder="Votre ville")),
                ),
                Row("country", placeholder="Votre pays"),
                # Utilisez des classes css pour le style
                style="""
                        border: 1px black solid; 
                        border-radius: 10px; 
                        margin-bottom: 1rem;
                    """,
            ),
        )
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

class UserCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'utisateur."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Données de connexion",
                Row(
                    Column(Field("name", placeholder="Votre nom")),
                    Column(Field("username", placeholder="Votre username")),
                ),
                Row(
                    Column(
                        Field("password1", placeholder="Votre mot de passe")
                    ),
                    Column(
                        Field(
                            "password2", placeholder="Répétez le mot de passe"
                        )
                    ),
                ),
                # Utilisez des classes css pour le style
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'adresse."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Adresse",
                Row(
                    Column(
                        Field("street", placeholder="Votre rue"),
                        css_class="col-md-10",
                    ),
                    Column(
                        Field("street_number", placeholder="N°"),
                        css_class="col-md-2",
                    ),
                ),
                Row(
                    Field(
                        "address_complement",
                        placeholder="Votre complément d'adresse",
                    ),
                ),
                Row(
                    Column(
                        Field("zip_code", placeholder="Code postal"),
                        css_class="col-md-4",
                    ),
                    Column(Field("city", placeholder="Votre ville")),
                ),
                Row("country", placeholder="Votre pays"),
                # Utilisez des classes css pour le style
                style="""
                        border: 1px black solid; 
                        border-radius: 10px; 
                        margin-bottom: 1rem;
                    """,
            ),
        )
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

class UserCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'utisateur."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Données de connexion",
                Row(
                    Column(Field("name", placeholder="Votre nom")),
                    Column(Field("username", placeholder="Votre username")),
                ),
                Row(
                    Column(
                        Field("password1", placeholder="Votre mot de passe")
                    ),
                    Column(
                        Field(
                            "password2", placeholder="Répétez le mot de passe"
                        )
                    ),
                ),
                # Utilisez des classes css pour le style
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'adresse."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Adresse",
                Row(
                    Column(
                        Field("street", placeholder="Votre rue"),
                        css_class="col-md-10",
                    ),
                    Column(
                        Field("street_number", placeholder="N°"),
                        css_class="col-md-2",
                    ),
                ),
                Row(
                    Field(
                        "address_complement",
                        placeholder="Votre complément d'adresse",
                    ),
                ),
                Row(
                    Column(
                        Field("zip_code", placeholder="Code postal"),
                        css_class="col-md-4",
                    ),
                    Column(Field("city", placeholder="Votre ville")),
                ),
                Row("country", placeholder="Votre pays"),
                # Utilisez des classes css pour le style
                style="""
                        border: 1px black solid; 
                        border-radius: 10px; 
                        margin-bottom: 1rem;
                    """,
            ),
        )
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

class UserCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'utisateur."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Données de connexion",
                Row(
                    Column(Field("name", placeholder="Votre nom")),
                    Column(Field("username", placeholder="Votre username")),
                ),
                Row(
                    Column(
                        Field("password1", placeholder="Votre mot de passe")
                    ),
                    Column(
                        Field(
                            "password2", placeholder="Répétez le mot de passe"
                        )
                    ),
                ),
                # Utilisez des classes css pour le style
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'adresse."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Adresse",
                Row(
                    Column(
                        Field("street", placeholder="Votre rue"),
                        css_class="col-md-10",
                    ),
                    Column(
                        Field("street_number", placeholder="N°"),
                        css_class="col-md-2",
                    ),
                ),
                Row(
                    Field(
                        "address_complement",
                        placeholder="Votre complément d'adresse",
                    ),
                ),
                Row(
                    Column(
                        Field("zip_code", placeholder="Code postal"),
                        css_class="col-md-4",
                    ),
                    Column(Field("city", placeholder="Votre ville")),
                ),
                Row("country", placeholder="Votre pays"),
                # Utilisez des classes css pour le style
                style="""
                        border: 1px black solid; 
                        border-radius: 10px; 
                        margin-bottom: 1rem;
                    """,
            ),
        )
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

class UserCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'utisateur."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Données de connexion",
                Row(
                    Column(Field("name", placeholder="Votre nom")),
                    Column(Field("username", placeholder="Votre username")),
                ),
                Row(
                    Column(
                        Field("password1", placeholder="Votre mot de passe")
                    ),
                    Column(
                        Field(
                            "password2", placeholder="Répétez le mot de passe"
                        )
                    ),
                ),
                # Utilisez des classes css pour le style
                style="""
                    border: 1px black solid; 
                    border-radius: 10px; 
                    margin-bottom: 1rem;
                """,
            ),
        )


class AddressCreationLayout(Layout):
    """Mise en page pour le formulaire de création
    d'adresse."""

    def __init__(self):
        super().__init__(
            Fieldset(
                "Adresse",
                Row(
                    Column(
                        Field("street", placeholder="Votre rue"),
                        css_class="col-md-10",
                    ),
                    Column(
                        Field("street_number", placeholder="N°"),
                        css_class="col-md-2",
                    ),
                ),
                Row(
                    Field(
                        "address_complement",
                        placeholder="Votre complément d'adresse",
                    ),
                ),
                Row(
                    Column(
                        Field("zip_code", placeholder="Code postal"),
                        css_class="col-md-4",
                    ),
                    Column(Field("city", placeholder="Votre ville")),
                ),
                Row("country", placeholder="Votre pays"),
                # Utilisez des classes css pour le style
                style="""
                        border: 1px black solid; 
                        border-radius: 10px; 
                        margin-bottom: 1rem;
                    """,
            ),
        )
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        
        

forms.py se simplifie

from .form_layouts import UserCreationLayout, AddressCreationLayout


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

        
class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""
from .form_layouts import UserCreationLayout, AddressCreationLayout


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

        
class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""
from .form_layouts import UserCreationLayout, AddressCreationLayout


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""
        
    class Meta(auth_forms.UserCreationForm):
        model = User
        fields = ("name", "username")

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = UserCreationLayout()

        
class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""
from .form_layouts import UserCreationLayout, AddressCreationLayout


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

        
class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""
from .form_layouts import UserCreationLayout, AddressCreationLayout


class UserCreationForm(auth_forms.UserCreationForm):
    """Formulaire de souscription pour les utilisateurs."""

        
class AddressCreationForm(forms.ModelForm):
    """Formulaire de création pour une adresse."""

    ...

    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self.fields["address_type"].choices = UserAddress.AdresseRoles.choices

        self.helper = FormHelper()
        self.helper.form_tag = False
        self.helper.layout = AddressCreationLayout()

Des éléments de mise en page avancés

Différents frameworks CSS

La documentation de crispy-forms

https://django-crispy-forms.readthedocs.io/