Académique Documents
Professionnel Documents
Culture Documents
html
.mobo
Blog d'un Pythoniste Djangonaute
1) L'installation et la configuration
C'est parti ! On suppose que tu as déjà installé python 3.5 avec virtualenvwrapper. Tu
crées donc ton environnement virtuel et tu installes les librairies requises:
LANGUAGE_CODE = 'fr'
TIME_ZONE = 'Europe/Paris'
INSTALLED_APPS = (
...
'crispy_forms',
'django_countries',
'bootstrap3_datetime',
'captcha',
'demo_django_crispy_forms.apps.core'
)
CRISPY_TEMPLATE_PACK = 'bootstrap3'
Il te su�it de migrer la base de données et de vérifier que tout est bon pour l'instant.
Depuis le répertoire racine du projet, tu fais:
2) Le modèle
class Registration(models.Model):
"""
Modèle de l'inscription
"""
CIVILITY_CHOICES = (
('M.', 'M.'),
('MME', 'Mme')
)
STREET_TYPE_CHOICES = (
('Boulevard', 'Boulevard'),
('Avenue', 'Avenue'),
('Cours', 'Cours'),
('Place', 'Place'),
('Rue', 'Rue'),
('Route', 'Route'),
('Voie', 'Voie'),
('Chemin', 'Chemin'),
('Square', 'Square'),
('Impasse', 'Impasse'),
('Rond-point', 'Rond-point'),
('Quai', 'Quai')
)
./manage.py makemigrations
./manage.py migrate
3) Le formulaire
Place au formulaire. J'ai rajouté des commentaires directement dans le code ci-dessous
pour expliquer les di�érentes étapes.
class RegistrationForm(forms.ModelForm):
"""
Formulaire d'inscription
"""
),
# Deuxième onglet
Tab(
# Label de l'onglet
'Étape 2 - Adresse',
# Liste des champs à afficher
'street_number',
'street_type',
'street',
'comp_1',
'comp_2',
'city',
'zip_code',
'country',
'phone',
# Tu rajoutes des boutons "Précédent" et "Suivant"
StrictButton(
'<span class="glyphicon glyphicon-arrow-left"
aria-hidden="true"></span> %s' % 'Précédent'
type='button',
css_class='btn-default btnPrevious',
),
StrictButton(
'<span class="glyphicon glyphicon-arrow-right"
aria-hidden="true"></span> %s' % 'Suivant',
type='button',
css_class='btn-default col-md-offset-8 btnNext'
)
),
# Troisième onglet
Tab(
# Label de l'onglet
'Étape 3 - Validation',
# Liste des champs à afficher dont les champs supplémentaire
'mail',
'confirmation_mail',
'comments',
'captcha',
# Tu rajoutes des boutons "Précédent" et "Valider"
StrictButton(
'<span class="glyphicon glyphicon-arrow-left"
aria-hidden="true"></span> %s' % "Précédent"
type='button',
css_class='btn-default btnPrevious',
),
StrictButton(
'<span class="glyphicon glyphicon-ok" \
aria-hidden="true"></span> %s' % "Valider",
type='submit',
css_class='btn-default col-md-offset-8'
)
),
),
)
def clean_confirmation_mail(self):
"""
Méthode pour vérifier que le mail correspond bien au
mail de confirmation lors de la validation du formulaire
"""
confirmation_mail = self.cleaned_data['confirmation_mail']
mail = self.cleaned_data['mail']
if mail != confirmation_mail:
raise forms.ValidationError(
"Le mail et le mail de confirmation ne sont pas identiques"
return confirmation_mail
class Meta:
# Tu définis le modèle utilisé
model = Registration
exclude = []
# Tu customises le champ date de naissance pour ajouter le date picker
widgets = {
'birth_date': DateTimePicker(
options={"format": "DD/MM/YYYY", "pickTime": False,
"useStrict": True, "viewMode": "years",
"startDate": "01/01/1900"},
attrs={'placeholder': 'ex: 05/11/1975'}
)
}
4) Les vues
Maintenant que tu as ton formulaire, il te faut une vue pour a�icher le formulaire et une
autre pour a�icher un message de confirmation après la validation de celui-ci.
class RegistrationCreate(CreateView):
"""
Affichage du formulaire
"""
model = Registration
form_class = RegistrationForm
success_url = reverse_lazy('core:success')
def registration_success(request):
"""
Message de confirmation
"""
return render(request, 'core/registration_success.html')
5) Les urls
Dans le fichier des urls du projet, tu vas inclure les urls de l'application core et l'url pour
le captcha.
urlpatterns = [
url(r'^admin/', admin.site.urls),
url(r'^', include(core_urls, namespace='core')),
url(r'^captcha/', include('captcha.urls')),
]
urlpatterns = [
url(r'^$', RegistrationCreate.as_view(), name='add'),
url(r'^success/$', registration_success, name='success'),
]
6) Les templates
Tu vas créer trois templates:
<!DOCTYPE html>
<html lang="fr">
<head>
<title>Mon site</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0"
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<link rel="stylesheet"
href="//cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap.min.css"
<link rel="stylesheet"
href="//cdn.jsdelivr.net/bootstrap/3.3.6/css/bootstrap-theme.min.css"
<script src="//cdn.jsdelivr.net/jquery/2.2.3/jquery.min.js"></script
{% block head-javascript %}{% endblock %}
</head>
<body>
<div class="container" role="main">
<div id="summary">
<div class="page-header">
{% block page-header %}{% endblock %}
</div>
</div>
{% block content %}
{% endblock %}
</div>
<script src="//cdn.jsdelivr.net/bootstrap/3.3.6/js/bootstrap.min.js"
{% block foot-javascript %}{% endblock %}
</body>
</html>
C'est une page html5 standard, qui contient les fichiers nécessaires à bootstrap, un block
page-header pour a�icher le titre de la page et un block content pour a�icher le
contenu de la page. Les templates suivants vont donc étendre base.html.
{% extends "base.html" %}
{% load crispy_forms_tags %}
{% block head-javascript %}
{{ form.media }}
{% endblock %}
{% block page-header %}
<h1>Inscription</h1>
{% endblock %}
{% block content %}
<div class="row">{% crispy form %}</div>
{% endblock %}
{% block foot-javascript %}
<script>
$( document ).ready( function() {
// On interdit le copier/coller du mail
$('#id_confirmation_mail').bind('copy paste', function(e) {
e.preventDefault();
});
// On affiche le calendrier lorsqu'on clique sur le champ date de naissance
$('#id_birth_date').click(function(){
$(this).parent().data("DateTimePicker").show();
});
// On teste la valeur de la date et on la force à vide si elle est mauvaise
$('#id_birth_date').change(function(e){
e.preventDefault();
e.stopPropagation();
var val = $(this).val();
var format = new RegExp("^\\d{2}\/\\d{2}\/\\d{4}$");
if(!format.test(val)) {
$(this).val("");
}
});
// Afficher l'onglet suivant en cliquant sur le bouton suivant
$('.btnNext').click(function(){
$('.nav-tabs > .active + li a').trigger('click');
$(".nav-tabs + .tab-content").find(":input:visible:first").focus
});
// Afficher l'onglet précédent en cliquant sur le bouton précédent
$('.btnPrevious').click(function(){
$('.nav-tabs > .active').prev('li').find('a').trigger('click'
$(".nav-tabs + .tab-content").find(":input:visible:first").focus
});
});
</script>
{% endblock %}
Pour crispy-forms, il ne faut que deux éléments ! Le {% load crispy_forms_tags %}, qui
permet d'utiliser le {% crispy form %} pour a�icher le formulaire.
Le {{ form.media }} est nécessaire au date picker et tout ce qui se trouve dans le block
foot-javascript permet de pousser un peu plus la customisation.
{% extends "base.html" %}
{% block page-header %}
<h1>Succès</h1>
{% endblock %}
{% block content %}
<div class="row">Votre inscription a été validée.</div>
{% endblock %}
7) La page d'administration
Pour pouvoir vérifier les futures inscriptions, tu ajoutes le modèle Registration dans
apps/core/admin.py:
class RegistrationAdmin(admin.ModelAdmin):
list_display = ('birth_name', 'last_name', 'first_name')
admin.site.register(Registration, RegistrationAdmin)
./manage.py createsuperuser
8) La vérification
Tout est fini ! Il ne reste plus qu'à vérifier que ça fonctionne correctement.
Tu démarres le serveur:
./manage.py runserver
Tu sais désormais utiliser un outil puissant pour générer tes nombreux formulaires ! Et
pour voir le résultat final, tu peux te rendre sur mon dépôt github.
8 Commentaires dotmobo
1 S'identifier
Participer à la discussion…
S'IDENTIFIER AVEC
OU INSCRIVEZ-VOUS SUR DISQUS ?
Nom
© 2018 - This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 International License
Propulsé par Pelican - Flex thème par Alexandre Vicenzi