web-dev-qa-db-fra.com

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 affiche toujours la valeur précédente dans l'attribut value de la balise d'entrée:

<input type="text" id="id_email" maxlength="75" class="required" value="[email protected]" name="email">

Je veux rendre le tag 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 ("[email protected]" dans cet exemple) à l'utilisateur . Comment obtenir la valeur du champ dans le modèle?

63
Eran Kampf

La solution proposée par Jens est correcte . Cependant, il s'avère que si vous initialisez votre ModelForm avec une instance (exemple ci-dessous), Django ne peuplera 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 remplit 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()
5
Eran Kampf

Cette demande de fonctionnalité a été corrigée dans Django 1.3. 

Voici le bug: https://code.djangoproject.com/ticket/10427

En gros, si vous utilisez quelque chose après la 1.3, dans les templates Django, vous pouvez faire:

{{ 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, () est omis, tandis que dans les méthodes Jinja2, les appels sont explicites.

Si vous voulez savoir quelle version de Django vous utilisez, elle vous dira quand vous exécuterez la commande runserver.

Si vous utilisez une version antérieure à 1.3, vous pouvez probablement utiliser le correctif publié dans le bogue ci-dessus: https://code.djangoproject.com/ticket/10427#comment:24

111
mlissner

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 l'initiale si vous le souhaitez) ou affichez les données POST telles que le cas échéant, une erreur de validation.

39
LeeMobile

Cela semble fonctionner.

{{ form.fields.email.initial }}
13
Rich

J'ai une solution simple pour vous!

{{ form.data.email }}

Je l'ai essayé et ça marche. Cela nécessite que votre vue remplisse la classe de formulaire avec les données POST.

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 ça vous aide. Si vous avez des questions s'il vous plaît faites le moi savoir.

13
Jens

{{form.field_name.value}} fonctionne pour moi

5
robertzp

Je voulais afficher la valeur d'un champ formset. J'ai conclu cette solution, qui devrait également fonctionner pour les formes normales:

{% if form.email.data %} {{ form.email.data }}
{% else %} {{ form.initial.email }} 
{% endif %}

Les solutions ci-dessus ne fonctionnaient pas très bien pour moi et je doute qu'elles fonctionnent si des formulaires préfixés (tels que des assistants et des jeux de formulaires) ... .. Les solutions utilisant {{ form.data.email }} ne peuvent pas fonctionner, car il s'agit d'une recherche dans un dictionnaire, et avec des formes préfixées, votre nom de champ ressemblerait à quelque chose comme '1-email' (assistant et forme préfixée) ou 'formulaire-1-email' (formset), et le signe moins (-) ne sont pas autorisés dans les expressions de recherche de modèle en pointillé.

{{form.field_name.value}} est uniquement Django 1.3+.

2
kosii

Si vous avez rempli le formulaire avec une instance et non avec POST data (comme le suggère la réponse suggérée), vous pouvez accéder aux données en utilisant {{form.instance.my_field_name}}.

1
monofonik

J'ai essayé quelques-unes des possibilités mentionnées, et voici comment j'ai résolu mon problème:

#forms.py
class EditProfileForm(forms.ModelForm):
    first_name = forms.CharField(label='First Name',
                                 widget=forms.TextInput(
                                 attrs={'class': 'form-control'}),
                                 required=False)
    last_name = forms.CharField(label='Last Name',
                                 widget=forms.TextInput(
                                 attrs={'class': 'form-control'}),
                                 required=False)
    # username = forms.CharField(widget=forms.TextInput(
    #                              attrs={'class': 'form-control'}),
    #                              required=True)
    address = forms.CharField(max_length=255, widget=forms.TextInput(
                                 attrs={'class': 'form-control'}),
                                 required=False)
    phoneNumber = forms.CharField(max_length=11,
                                 widget=forms.TextInput(
                                 attrs={'class': 'form-control'}),
                                 required=False)
    photo = forms.ImageField(label='Change Profile Image', required=False)

    class Meta:
        model = User
        fields = ['photo', 'first_name', 'last_name', 'phoneNumber', 'address']
                  # 'username',



#views.py
def edit_user_profile(request, username):
    user = request.user
    username = User.objects.get(username=username)
    user_extended_photo = UserExtended.objects.get(user=user.id)
    form = EditProfileForm(request.POST or None, request.FILES, instance=user)
    user_extended = UserExtended.objects.get(user=user)
    if request.method == 'POST':
        if form.is_valid():
            # photo = UserExtended(photo=request.FILES['photo'] or None, )
            user.first_name = request.POST['first_name']
            user.last_name = request.POST['last_name']
            user_extended.address = request.POST['address']
            user_extended.phoneNumber = request.POST['phoneNumber']
            user_extended.photo = form.cleaned_data["photo"]
            # username = request.POST['username']
            user_extended.save()
            user.save()

            context = {
                'form': form,
                'username': username,
                'user_extended_photo': user_extended_photo,
            }

            return render(request, 'accounts/profile_updated.html', context)
    else:
        photo = user_extended.photo
        first_name = user.first_name
        last_name = user.last_name
        address = user_extended.address
        phoneNumber = user_extended.phoneNumber
        form = EditProfileForm(
            initial={'first_name': first_name, 'last_name': last_name,
                                   'address': address, 'phoneNumber': phoneNumber,
                                   'photo': photo})
    context = {
        'form': form,
        'username': username,
        'user_extended_photo': user_extended_photo,

    }
    return render_to_response('accounts/edit_profile.html', context,
                                 context_instance=RequestContext(request))

#edit_profile.html
  <form action="/accounts/{{ user.username }}/edit_profile/" method="post" enctype='multipart/form-data'>
                                    {% csrf_token %}
                                        <div class="col-md-6">
                                            <div class="form-group">
                                                {{ form.as_p }}
                                            </div>
                                        </div>
                                    <br><br><br><br><br><br><br><br><br><br><br><br><br><br><br>
                                    <button type="submit"  value="Update Profile" class="btn btn-info btn-fill pull-right">Update Profile</button>
                                    <div class="clearfix"></div>
                                </form>

J'essaie d'expliquer cela de manière à ce que les débutants trouvent plus facile à comprendre. Portez une attention particulière au else:

        photo = user_extended.photo
        first_name = user.first_name
        last_name = user.last_name
        address = user_extended.address
        phoneNumber = user_extended.phoneNumber
        form = EditProfileForm(
            initial={'first_name': first_name, 'last_name': last_name,
                                  'address': address, 'phoneNumber': phoneNumber,
                                  'photo': photo}) 

C’est ce qui obtient la valeur attrib, par exemple:

<p><label for="id_first_name">First Name:</label> <input class="form-control" id="id_first_name" name="first_name" type="text" value="Emmanuel" /></p>
<p><label for="id_last_name">Last Name:</label> <input class="form-control" id="id_last_name" name="last_name" type="text" value="Castor" /></p>
1
Emmanuel Caster
{{form.fields.email}}
0
shanyu

Sur Django 1.2, {{form.data.field}} et {{form.field.data}} sont tous corrects, mais pas {{form.field.value}}.
Comme d'autres l'ont dit, {{form.field.value}} est uniquement Django 1.3+, mais il n'y a pas de spécification dans https://docs.djangoproject.com/fr/1.3/topics/forms/ . Vous pouvez le trouver dans https://docs.djangoproject.com/fr/1.4/topics/forms/ .

0
bigwind