86 votes

Comment afficher la valeur d'un champ de formulaire Django dans un modèle ?

J'ai un formulaire avec une propriété email.

Lorsque vous utilisez {{ form.email }} en cas d'erreur de validation, Django rend toujours la valeur précédente dans l'attribut value de la balise input :

<input type="text" id="id_email" maxlength="75" class="required"
       value="some@email.com" name="email">

Je veux rendre la balise d'entrée moi-même (pour ajouter du code JavaScript et une classe d'erreur en cas d'erreur). Par exemple, voici mon modèle au lieu de {{ form.email }} :

<input type="text" autocomplete="on" id="id_email" name="email"
       class="email {% if form.email.errors %} error {% endif %}">

Cependant, cela n'affiche pas la valeur erronée ( some@email.com dans cet exemple) à l'utilisateur.

Comment obtenir la valeur du champ dans le modèle ?

0 votes

La documentation contient quelques exemples utiles pour travailler avec des modèles de formulaires.

145voto

mlissner Points 2158

Il s'agissait d'une demande de fonctionnalité qui a été corrigée dans Django 1.3.

Voilà le problème : https://code.djangoproject.com/ticket/10427

En gros, si vous exécutez quelque chose après la version 1.3, vous pouvez faire ce qui suit dans les modèles Django :

{{ form.field.value|default_if_none:"" }}

Ou dans Jinja2 :

{{ form.field.value()|default("") }}

Notez que field.value() est une méthode, mais dans les modèles Django () sont omis, alors que dans Jinja2 les appels de méthode sont explicites.

Si vous voulez savoir quelle version de Django vous exécutez, il vous le dira lorsque vous utiliserez la commande runserver.

Si vous êtes sur une version antérieure à la 1.3, vous pouvez probablement utiliser la correction postée dans le bogue ci-dessus : https://code.djangoproject.com/ticket/10427#comment:24

0 votes

C'est la bonne réponse pour Django >= 1.3. Ce point était manifestement absent de la documentation de Django, mais il semble maintenant avoir été corrigé (au moins dans la version dev). code.djangoproject.com/ticket/16851

21 votes

Cela a l'effet désagréable que si form.field.value est None alors le texte "Aucun" sera affiché. Pour afficher une chaîne vide à la place, utilisez {{ form.field.value|default_if_none:"" }}

0 votes

+1 pour avoir mentionné que cela ne fonctionne que dans >=1.3. J'utilise toujours la version 1.2 et je n'arrivais pas à comprendre pourquoi cela ne fonctionnait pas avant de lire ceci.

47voto

LeeMobile Points 1273

Vous pouvez le faire à partir du modèle avec quelque chose comme ceci :

{% if form.instance.some_field %}
      {{form.instance.some_field}}
{% else %}
      {{form.data.some_field}}
{% endif %}

Cela affichera la valeur de l'instance (si le formulaire est créé avec une instance, vous pouvez utiliser initial à la place si vous le souhaitez), ou bien afficher les données POST, comme lorsqu'une erreur de validation se produit.

2 votes

Une honte que cette réponse soit enterrée si profondément ! C'est la façon de le faire sans ajouter de code à votre projet ou Parcheando votre django.

2 votes

Pouvez-vous m'expliquer ce que je dois remplir dans ces champs improvisés ? J'ai essayé plusieurs variantes et cela n'a pas fonctionné.

17voto

Rich Points 4452

Cela semble fonctionner.

{{ form.fields.email.initial }}

11 votes

Je peux me tromper, mais je crois que cela affichera la valeur initiale à chaque fois. Par exemple, essayez de soumettre le formulaire de manière à ce qu'il génère une erreur et vous verrez que le formulaire qui se recharge en affichant l'erreur aura à nouveau la valeur initiale, et non la valeur que l'utilisateur a entrée avant qu'il ne génère l'erreur.

16voto

Jens Points 2939

J'ai une solution simple pour vous !

{{ form.data.email }}

J'ai essayé ceci et cela a fonctionné. Cela nécessite que votre vue remplisse la classe de formulaire avec les données POST.

Un exemple très simple :

def your_view(request):
  if request.method == 'POST':
    form = YourForm(request.POST)
    if form.is_valid():
      # some code here
  else:
    form = YourForm()

  return render_to_response('template.html', {'form':form})

J'espère que cela vous aidera. Si vous avez des questions, n'hésitez pas à m'en faire part.

0 votes

Les données nettoyées ne contiendront pas le champ email s'il n'a pas pu être nettoyé lors de la validation.

0 votes

Vous avez raison. Vous ne pourrez pas accéder aux données nettoyées si is_valid() échoue. Je cherche une autre solution.

0 votes

J'ai mis à jour mon code. Il y avait une solution simple. Au lieu de cleaned_data, utilisez simplement data. Cela fonctionne même si la validation échoue !

6voto

Eran Kampf Points 3285

La solution proposée par Jens est correcte. Cependant, il s'avère que si vous initialisez votre ModelForm avec un fichier de type instance (exemple ci-dessous), django ne remplira pas les données :

def your_view(request):   
    if request.method == 'POST':
        form = UserDetailsForm(request.POST)
        if form.is_valid():
          # some code here   
        else:
          form = UserDetailsForm(instance=request.user)

J'ai donc créé ma propre classe de base ModelForm qui alimente les données initiales :

from django import forms 
class BaseModelForm(forms.ModelForm):
    """
    Subclass of `forms.ModelForm` that makes sure the initial values
    are present in the form data, so you don't have to send all old values
    for the form to actually validate.
    """
    def merge_from_initial(self):
        filt = lambda v: v not in self.data.keys()
        for field in filter(filt, getattr(self.Meta, 'fields', ())):
            self.data[field] = self.initial.get(field, None)

Ensuite, l'exemple de vue simple ressemble à ceci :

def your_view(request):   if request.method == 'POST':
    form = UserDetailsForm(request.POST)
    if form.is_valid():
      # some code here   
    else:
      form = UserDetailsForm(instance=request.user)
      form.merge_from_initial()

0 votes

Je ne vois pas pourquoi django ne fait pas cela par défaut... Je pense que je vais soumettre un patch et voir ce que les gens en disent.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X