WTForms - 显示属性值而非HTML字段
我想在我的WTForms表单中重复使用一个模板:
<th>${form.name.label}</th>
<td>${form.name()}</td>
...
但是,在我的编辑页面上,我希望输入框正常显示(比如TextField
、SelectField
等),而在查看页面上,我只想显示属性的值,而不是带有值的输入框。
编辑页面:
<th>Name:</th>
<td><input type="text" value="Current Name" name="name" id="name"/></td>
查看页面:
<th>Name:</th>
<td>Current Name</td>
我知道可以通过form.name.data
来获取字段的值,但有没有办法让我在调用form.name()
时保持相同的模板,并且能够切换输出<input type="text"...
还是当前名称
呢?
3 个回答
1
根据Sarah的回答和在WTForms-Components上找到的代码,我使用以下方法快速将一个表单的所有字段变成只读和禁用的字段。
假设我们有一个名为ProfileForm的表单,定义如下:
class ProfileEditForm(Form):
title = StringField("Title", validators=[validators.required("Please enter your title.")])
first_name = StringField("First Name", validators=[validators.required("Please enter your first name.")])
middle_name = StringField("Middle Name")
last_name = StringField("Last Name", validators=[validators.required("Please enter your last name.")])
organisation = StringField("Company Name", validators=[validators.required("Please enter your company name.")])
organisation_website = StringField("Company Website")
# more fields ...
接下来,定义一个类(基于WTForms-Components中的ReadOnlyWidgetProxy):
class ReadOnlyAndDisabledWidgetProxy(object):
def __init__(self, widget):
self.widget = widget
def __getattr__(self, name):
return getattr(self.widget, name)
def __call__(self, field, **kwargs):
kwargs.setdefault('readonly', True)
kwargs.setdefault('disabled', True)
return self.widget(field, **kwargs)
现在可以像下面这样继承ProfileForm:
class ReadOnlyProfileForm(ProfileForm):
def __init__(self, *args, **kwargs):
super(ReadOnlyProfileForm, self).__init__(*args, **kwargs)
for field_name in self._fields:
field_property = getattr(self, field_name)
field_property.widget = ReadOnlyAndDisabledWidgetProxy(field_property.widget)
6
上面Sarah的回答让我找到了一个相关问题的解决办法:如果你想让某些字段只能读取,怎么办呢?在这种情况下,不需要在运行时对表单对象进行复杂的修改,你可以定义一个新的ROTextField
类型(比如说),它总是只显示纯值。比如:
from wtforms.widgets import Input
from wtforms.fields import StringField
class TextOutput(Input):
def __call__(self, field, **kwargs):
return kwargs.get('value', field._value())
class ROTextField(StringField):
widget = TextOutput()
现在定义你的字段时加上只读属性:
class UserPrefs(Form):
name = ROTextField('name', default='Jon')
# ...
思考这个问题让我更好地理解了WTForms是怎么工作的。把这个留在这里,希望能帮助到其他人解决类似的问题。
8
我创建了一个自定义的小部件:
from wtforms.fields import Field
class PlainTextWidget(object):
def __call__(self, field, **kwargs):
return field.data if field.data else ''
然后,在我的视图页面上,我添加了以下内容:
form = MyForm(obj=myDataRow)
fields = [val for val in form._fields]
for fieldName in fields:
fieldProp = getattr(form, fieldName)
setattr(fieldProp, 'widget', PlainTextWidget())