如何在模板中显示 Django 表单字段的值?

我有一个具有电子邮件属性的表单。

在出现验证错误的情况下使用 {{ form.email }}时,Django 仍然在输入标记的 value 属性中呈现前一个值:

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

我想自己呈现输入标记(以便在发生错误时添加一些 JavaScript 代码和一个错误类)。例如,这是我的模板,而不是 {{ form.email }}:

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

但是,这不会向用户显示错误的值(本例中为 some@email.com)。

如何在模板中获取字段的值?

177396 次浏览
\{\{form.fields.email}}

I have a simple solution for you!

\{\{ form.data.email }}

I tried this and it worked. This requires your view to populate the form class with the POST data.

Very simple example:

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})

Hope that helps you. If you have any questions please let me know.

The solution proposed by Jens is correct. However, it turns out that if you initialize your ModelForm with an instance (example below) django will not populate the data:

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)

So, I made my own ModelForm base class that populates the initial data:

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)

Then, the simple view example looks like this:

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()

This seems to work.

\{\{ form.fields.email.initial }}

If you've populated the form with an instance and not with POST data (as the suggested answer requires), you can access the data using \{\{ form.instance.my_field_name }}.

You can do this from the template with something like this:

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

This will display the instance value (if the form is created with an instance, you can use initial instead if you like), or else display the POST data such as when a validation error occurs.

\{\{ form.field_name.value }} works for me

I wanted to display the value of a formset field. I concluded this solution, which should work for normal forms too:

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

The above solutions didn't worked very well for me, and I doubt they would work in case of prefixed forms (such as wizards and formsets). The solutions using \{\{ form.data.email }} can't work, because it is a dictionary lookup, and with prefixed forms your field name would look something like '1-email' (wizard and prefixed form) or 'form-1-email' (formset), and the minus sign (-) are not allowed in dotted template lookup expressions.

\{\{form.field_name.value}} is Django 1.3+ only.

This was a feature request that got fixed in Django 1.3.

Here's the bug: https://code.djangoproject.com/ticket/10427

Basically, if you're running something after 1.3, in Django templates you can do:

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

Or in Jinja2:

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

Note that field.value() is a method, but in Django templates ()'s are omitted, while in Jinja2 method calls are explicit.

If you want to know what version of Django you're running, it will tell you when you do the runserver command.

If you are on something prior to 1.3, you can probably use the fix posted in the above bug: https://code.djangoproject.com/ticket/10427#comment:24

On Django 1.2, \{\{ form.data.field }} and \{\{ form.field.data }} are all OK, but not \{\{ form.field.value }}.
As others said, \{\{ form.field.value }} is Django 1.3+ only, but there's no specification in https://docs.djangoproject.com/en/1.3/topics/forms/. It can be found in https://docs.djangoproject.com/en/1.4/topics/forms/.

I tried a few of the mentioned possibilities, and this is how I solved my problem:

#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>

I am trying to explain this in a way so that beginners may find it easier to understand. Pay close attention to the 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})

It is what gets the value attrib, e.g.:

<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>

For check box with its items:

{% for item in people.q %}
<div class="form-check form-switch ">
<label class="form-check-label" for="\{\{ item.id_for_label }}">\{\{ item.data.label }}</label>
<input class="form-check-input" type="checkbox" id="\{\{ item.id_for_label }}" value="\{\{ item.data.value }}">
</div>
{% endfor %}

q is field name.