在WTForms SelectField中为选项添加CSS类
有没有人能告诉我怎么给choices的值添加CSS类呢?我想给每个选项的背景换成小图片,那我该怎么用wtforms和CSS来实现呢?
class RegisterForm(Form):
username = TextField('username', [validators.Length(min=3, max=50), validators.Required()])
img_url = SelectField('avatar',
choices=[('static/images/avatars/1.jpg', '1'),
('static/images/avatars/2.jpg', '2'),
('static/images/avatars/3.jpg', '3'),
('static/images/avatars/4.jpg', '4'),
('static/images/avatars/5.jpg', '5'),
('static/images/avatars/6.jpg', '6'),
('static/images/avatars/7.jpg', '7'),
('static/images/avatars/8.jpg', '8'),
('static/images/avatars/9.jpg', '9'),
('static/images/avatars/10.jpg','10')])
2 个回答
我想告诉你,其实这个问题可以解决,不需要去修改库的代码或者重写wtforms。这个库本身是支持的,只是方式不太直接。我之所以知道这一点,是因为我遇到了和你一样的问题,试着为WTForms写了一个修复方案,还自己提交了一个PR,结果后来发现其实可以直接这样做(我花了好几天才弄明白这一点):
>>> from wtforms import SelectField, Form
>>> class F(Form):
... a = SelectField(choices=[('a', 'Apple'), ('b', 'Banana')])
...
>>> i = 44
>>> form = F()
>>> for subchoice in form.a:
... print subchoice(**{'data-id': i})
... i += 1
...
<option data-id="44" value="a">Apple</option>
<option data-id="45" value="b">Banana</option>
你可以在这里看到讨论:
https://github.com/wtforms/wtforms/pull/81
如果你深入了解 WTForms
的内部,会发现一个叫 SelectField
的小组件类。
这是用来生成 HTML 字符串的方法:
@classmethod
def render_option(cls, value, label, selected, **kwargs):
options = dict(kwargs, value=value)
if selected:
options['selected'] = True
return HTMLString('<option %s>%s</option>' % (html_params(**options), escape(text_type(label))))
这是 __call__
方法,它会调用上面定义的 render_options
函数。
def __call__(self, field, **kwargs):
kwargs.setdefault('id', field.id)
if self.multiple:
kwargs['multiple'] = True
html = ['<select %s>' % html_params(name=field.name, **kwargs)]
for val, label, selected in field.iter_choices():
html.append(self.render_option(val, label, selected))
html.append('</select>')
return HTMLString(''.join(html))
你不能仅仅通过创建一个 SelectField
来添加 class
属性。这样做会隐式地创建 Option
实例。在渲染时,这些隐式实例的 render_options
方法只会用 val
、selected
和 label
这些参数来调用。
你可以在之后访问这些隐式的 Option
实例,但这并不是没有问题。如果你看看 @Johnston 的例子:
>>> i = 44
>>> form = F()
>>> for subchoice in form.a:
... print subchoice(**{'data-id': i})
... i += 1
他正是这样做的。不过,你必须在渲染时提供类的属性。调用 subchoice(**{'data-id': i})
实际上会输出预期的 HTML
。如果你把 WTForms
和模板引擎结合使用,这就会造成问题。因为像 jinja
这样的模板引擎会为你调用这些渲染函数。
如果你想要这种行为,我建议你自己实现一个 SelectField
,这样可以让你把属性传递给隐式的 Option
实例。这样模板引擎就可以直接调用 render
,而你可以把表单的定义集中在你的 forms.py
文件中。