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


78

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

当使用{{ 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向用户显示错误的值(在此示例中)。

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


该文档提供了一些使用表单模板的
djvg

Answers:


128

这是一项功能请求,已在Django 1.3中修复。

错误是这样的:https//code.djangoproject.com/ticket/10427

基本上,如果您在1.3之后运行,则可以在Django模板中执行以下操作:

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

或在Jinja2中:

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

注意,这field.value()是一个方法,但是在Django模板()中省略了,而在Jinja2中,方法调用是显式的。

如果您想知道正在运行的Django版本,它将在执行runserver命令时告诉您。

如果您使用的是1.3之前的版本,则可以使用上述错误中发布的修复程序:https : //code.djangoproject.com/ticket/10427#comment:24


对于Django> = 1.3,这是正确的答案。django文档中明显没有此功能,但现在看来已得到修复(至少在开发版本中)。code.djangoproject.com/ticket/16851
zlovelady 2012年

19
这具有令人讨厌的效果,如果form.field.valueNone,则将显示文本“无”。要显示空字符串,请使用{{ form.field.value|default_if_none:"" }}
cberzan

+1(仅在> = 1.3中有效)。我仍在运行1.2,直到我读到这篇文章,才弄清楚为什么它不起作用。
Wipqozn 2012年

{{ form.initial.fieldname }}此处使用(Django 1.2.3)。
santiagopim 2014年

1
@santiagopim我可能是错的,但我相信这将每次都为您提供初始值,而不是为用户输入值。例如,制作一个引发错误而不是提交的表单,您将看到提交后用户的输入切换为初始值,而不是保留用户的输入。
mlissner 2014年

42

您可以从模板执行以下操作:

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

这将显示实例值(如果表单是使用实例创建的,则可以根据需要使用Initial代替),或者显示POST数据(例如,发生验证错误时)。


2
可惜这个答案被埋得那么深!这是一种无需添加任何代码到项目或修补django的方法。
w-- 2011年

2
您能否将我要填写的内容扩展到那些领域?我尝试了一些变体,但没有成功。
jordaninternets 2012年

17

这似乎有效。

{{ form.fields.email.initial }}

11
我可能会误会,但是我相信每次都会显示初始值。例如,尝试提交表单以引发错误,您将看到重新加载以显示错误的表单将再次具有初始值,而不是用户在引发错误之前输入的值。
mlissner

16

我有一个简单的解决方案给您!

{{ form.data.email }}

我尝试了一下,它奏效了。这需要您的视图用POST数据填充表单类。

很简单的例子:

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

希望对您有帮助。如果您有任何疑问,请告诉我。


如果在验证过程中无法清除,则清除的数据将不包含电子邮件字段。
shanyu 2010年

你是对的。如果is_valid()失败,您将无法访问cleaned_data。我正在寻找另一种解决方案。
詹斯2010年

我更新了我的代码。有一个简单的解决方案。代替cleaned_data只是使用数据。即使验证失败也可以!
詹斯

数据对我不起作用... {{form.description}}提供了具有正确值的控件{{form.data.description}}为空(实际上,{{form.data}}返回了{})
Eran Kampf 2010年

顺便说一句,我正在通过以下方式初始化表单:form_details = forms.UserDetailsForm(instance = request.user)
Eran Kampf 2010年


5

Jens提出的解决方案是正确的。但是,事实证明,如果使用实例(下面的示例)初始化ModelForm,则django将不会填充数据:

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)

因此,我制作了自己的ModelForm基类,用于填充初始数据:

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)

然后,简单视图示例如下所示:

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

我不明白django为何默认不这样做……我想我将提交一个补丁,看看人们对此有何评论。
伊兰·坎普夫

3

我尝试了一些提到的可能性,这就是我解决问题的方式:

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

我正在尝试以某种方式进行解释,以便初学者可能更容易理解。密切注意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}) 

它是获取值属性的原因,例如:

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

2

如果您使用实例而不是POST数据填充表单(按照建议的答案要求),则可以使用{{form.instance.my_field_name}}访问数据。


2

我想显示一个表单集字段的值。我总结了此解决方案,该解决方案也应适用于普通形式:

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

上面的解决方案对我来说不是很好,我怀疑它们是否可以在带前缀的表单(例如向导和表单集)的情况下使用。使用的解决方案{{ form.data.email }}不起作用,因为它是字典查找,并且带有前缀形式的字段名看起来像是“ 1-email”(向导和前缀形式)或“ form-1-email”(formset),并且点分模板查找表达式中不允许使用减号(-)。

{{form.field_name.value}} 仅适用于Django 1.3+。



By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.