Date Picker dans une class based view

Petite astuce permettant de gérer un date picker (calendrier qui apparaît pour la saisie d’une date dans un champ date) avec Django, Crispy-forms, bootstrap 5.

Cette astuce est très courte, mais j’ai passé plus d’une heure à trouver une solution qui me convenait, c’est la raison pour laquelle je la mets ici.

J’ai trouvé plein de solutions sur le web qui permettaient de le faire, en ajoutant notamment des modules plus ou moins bien faits, ou des scripts javascripts, des css et tout ça. Je voulais rester simple. Mes contraintes étaient les suivantes :

  • rester sur une class based view, donc sans form.py
  • utiliser uniquement le type="date" de la balise <input> qui permet d’avoir un date picker avec un navigateur moderne
  • rester avec une génération automatique d’un formulaire en bootstrap 5 avec le très minimaliste filtre crispy dans ma template :
{{ form|crispy }}

Là où j’ai beaucoup galéré, c’est parce que je pensais qu’il fallait changer l’attribut (attrs) type au niveau des widgets des champs date, alors qu’il faut changer l’input_type. Une fois qu’on a compris ça, c’est tout simple. Dans votre views.py, il faut ajouter une modification du formulaire par la fonction get_form(self) qui modifie le type de champ input car bien que le type de champ soit models.Datefield dans votre models.py, il se traduira par un input de type « text » dans le formulaire généré. Le views.py ressemble à ça :

class TotoCreateView(LoginRequiredMixin, CreateView):
    model = Toto
    fields = ['name', 'description', 'bdate', 'adate']
    ...

    
    def get_form(self):
        form = super().get_form()
        form.fields['bdate'].widget.input_type = 'date'
        form.fields['adate'].widget.input_type = 'date'
        return form

Et voilà, c’est simple, mais j’en ai bavé, donc j’espère que ça pourra être utile à quelqu’un.