将Django表单字段更改为隐藏字段

175

我有一个Django表单,其中包含一个RegexField,它与普通文本输入字段非常相似。

在我的视图中,根据某些条件,我希望将其从用户隐藏,并尽可能保持表单的相似性。如何最好地将此字段转换为HiddenInput字段?

我知道可以使用以下方式设置字段上的属性:

form['fieldname'].field.widget.attr['readonly'] = 'readonly'

我可以使用以下代码设置所需的初始值:

form.initial['fieldname'] = 'mydesiredvalue'

然而,这不会改变小部件的形式。

最好/最符合 "Django 风格" / 最不 "hacky" 的方法是使此字段成为 <input type="hidden"> 字段?

12个回答

265
这可能也很有用:{{ form.field.as_hidden }}

6
在我看来,这是最好的答案。我一直讨厌使用“控制器”Python代码来确定表单字段的显示方式。 - trpt4him
1
我经常使用crispyforms制作通用表单模板。如果您使用crispyforms或者您在简单的for循环中显示字段,因为您希望在表单类中有表单结构,则表单中的小部件覆盖是一个好的方法。但是,如果您将表单呈现管理到模板中,那么这种解决方案确实更加清晰/干净。 - christophe31
值得注意的是,这似乎会清除之前应用于该字段的任何类... - John Aaron
非常棒,帮了我很多。 - callmebob

222
如果您有自定义的模板和视图,您可以排除字段,并使用{{ modelform.instance.field }}来获取值。
另外,在视图中,您可能更喜欢使用:
field = form.fields['field_name']
field.widget = field.hidden_widget()

但我不确定它是否能保护post方法中的保存方法。

编辑:具有多个值的字段不支持将 HiddenInput 用作输入类型,因此请改为使用该字段的默认隐藏输入小部件。


2
在使用这个解决方案后,在 is_valid 方法中我得到了一个“”不是主键的有效值。 - Jens Timmerman
听起来很奇怪。我认为这与其他事情有关,你是否正在将对象的主键显示为HiddenInput?如果是,那么你不应该这样做。 - christophe31
也许这是不言自明的,但在此之前您需要导入表单才能使其工作。from django import forms - teewuane
4
在1.7版本中,使用以下语法:hidden_field_name = forms.CharField(label='reset', max_length=256, widget=forms.HiddenInput()) 其中关键部分是末尾的新小部件语法。您可以根据需要进行调整。 - Marc

90

一个对我有效的选项,是将原始表单中的字段定义为:

forms.CharField(widget = forms.HiddenInput(), required = False)

当你在新的类中覆盖它时,它会保持原来的位置。


54
首先,如果您不希望用户修改数据,则似乎更清晰的做法是排除该字段。将其包含为隐藏字段只会增加要发送的数据量,并在您不希望他们修改时邀请恶意用户进行修改。如果您有充分理由需要包含该字段但隐藏它,可以向modelform的构造函数传递一个关键字参数。或许可以像这样:
class MyModelForm(forms.ModelForm):
    class Meta:
        model = MyModel
    def __init__(self, *args, **kwargs):
        from django.forms.widgets import HiddenInput
        hide_condition = kwargs.pop('hide_condition',None)
        super(MyModelForm, self).__init__(*args, **kwargs)
        if hide_condition:
            self.fields['fieldname'].widget = HiddenInput()
            # or alternately:  del self.fields['fieldname']  to remove it from the form altogether.

然后在您的视图中:

form = MyModelForm(hide_condition=True)

我更喜欢这种方法,而不是在视图中修改模型表单的内部结构,但这只是个人口味问题。


13
简单提示:使用kwargs.pop('hide_condition', False)代替kwargs['hide_condition']。这样做可以处理没有参数的情况,同时具有默认值并且还能在同一时间删除该参数。 - christophe31
2
感谢您的提示,christophe31。我已经采纳了您的建议,因为它使代码更加清晰易懂。 - rych
2
使用这种方式,是否可能完全隐藏字段?就像设置class Meta:exclude = [“fieldname”]一样。 这里的问题是Meta方法是“静态”的,但我需要一些动态的东西。请参见http://stackoverflow.com/questions/20243735/django-show-admin-field-on-demand/20244351。 - Themerius
你可以使用def init(self, hide_condition=True, *args, **kwargs)这种最干净的方式... - Visgean Skeloru

40

对于范式化,您可以执行以下操作:

class MyModelForm(forms.ModelForm):
    slug = forms.CharField(widget=forms.HiddenInput())

如果您有模型表单,您可以执行以下操作

class MyModelForm(forms.ModelForm):
    class Meta:
        model = TagStatus
        fields = ('slug', 'ext')
        widgets = {'slug': forms.HiddenInput()}

您也可以覆盖__init__方法

class Myform(forms.Form):
    def __init__(self, *args, **kwargs):
        super(Myform, self).__init__(*args, **kwargs)
        self.fields['slug'].widget = forms.HiddenInput()

我收到了 crbug/1173575,非 JS 模块文件已被弃用。 - AnonymousUser

9
如果您希望该字段始终处于隐藏状态,请使用以下方法:
class MyForm(forms.Form):
    hidden_input = forms.CharField(widget=forms.HiddenInput(), initial="value")

如果您想以条件方式隐藏字段,则可以执行以下操作:
form = MyForm()
if condition:
    form.fields["field_name"].widget = forms.HiddenInput()
    form.fields["field_name"].initial = "value"

1
@Ashley 这有一个关键的不同之处。ShayRybak的回答没有包括如何向隐藏输入添加值,而我的回答则包括了。 - Zags
@Ashley,确实如此。问题是“制作隐藏字段的最简单方法是什么”。如果该字段始终处于隐藏状态(正如我的答案所规定的那样),最好在字段定义中设置值。 - Zags

3

模型示例:

models.py

from django.db import models


class YourModel(models.Model):
    fieldname = models.CharField(max_length=255, default="default")

在你的表单中,可以使用ModelForm添加小部件。要将其隐藏,请按照下面所示添加'type': 'hidden'forms.py
from .models import YourModel
from django import forms


class YourForm(forms.ModelForm):


    class Meta:
        model = YourModel
        fields = ('fieldname',)

        widgets = {
            'fieldname': forms.TextInput(attrs={'type': 'hidden'}),
        }

如果您不知道如何将其添加到views.py文件中,这里有一些相关视频。

如果您使用函数视图

https://www.youtube.com/watch?v=6oOHlcHkX2U


如果您使用类视图

https://www.youtube.com/watch?v=KB_wDXBwhUA


2

如果您想隐藏和禁用字段以保护其中的数据。如其他人所提到的,使用hiddenInput小部件并将其禁用。

在您的表单init

示例:

        if not current_user.is_staff:
           self.base_fields['pictureValid'].disabled = True
           self.base_fields['pictureValid'].widget = forms.HiddenInput()

2
{{ form.field}}
{{ form.field.as_hidden }}

使用jinja格式,我们可以同时拥有可见的表单字段和隐藏的表单字段。

1
使用{{ form.field.as_hidden }}的解决方案已经在这个答案中提供。 - Gino Mempin

1

使用render_field非常简单 {% render_field form.field hidden=True %}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接