Python 在WTForms中创建具有自定义属性的selectfield选项

Python 在WTForms中创建具有自定义属性的selectfield选项,python,flask,wtforms,Python,Flask,Wtforms,我正在尝试创建一个SelectField或SelectMultipleField,允许我将属性添加到它的标记中。我正在尝试添加属性,如数据id或另一个数据-\uuuuuuuu。我还没有弄明白怎么做,因为似乎只可能将属性添加到标记本身,而不可能添加选项。 最终结果应该是: <select id="regularstuff-here" name="regular-name-here"> <option value="1" data-id="somedata here" >

我正在尝试创建一个
SelectField
SelectMultipleField
,允许我将属性添加到它的
标记中。我正在尝试添加属性,如
数据id
或另一个
数据-\uuuuuuuu
。我还没有弄明白怎么做,因为似乎只可能将属性添加到
标记本身,而不可能添加选项。
最终结果应该是:

<select id="regularstuff-here" name="regular-name-here">
  <option value="1" data-id="somedata here" >Some Name here</option>
  <option value="2" data-id="somedata here" >Some Name here</option>
</select>
如果我看看这个方法:

@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))))
@classmethod
def render_选项(cls、值、标签、选定、**kwargs):
选项=dict(kwargs,值=值)
如果选择:
选项['selected']=True
返回HTMLString(“%s%”(html参数(**选项),
转义(文本类型(标签)))

因此,您似乎无法将任何额外的参数传递给呈现
选项的方法。

我只想说,这是可能的,无需对wtforms进行修补或重写。库代码确实支持它,尽管不是很直截了当。我发现这一点是因为我试图为WTForms编写一个修复程序,并亲自提交了一份PR,后来发现您可以这样做(我花了几天时间试图解决这个问题):

>>从wtforms导入选择字段,表单
>>>F类(表格):
...    a=SelectField(选项=[('a','Apple'),('b','Banana'))
... 
>>>i=44
>>>form=F()
>>>对于表a中的次选择:
...     打印子选择(**{'data-id':i})
...     i+=1
... 
苹果
香蕉
请参见此处的车队:

如果您(像我一样)希望在选项数组中按选项存储自定义属性,而不是在渲染时提供,以下自定义的“AttribSelectField”和小部件应该会有所帮助。这些选项将变成(值、标签、渲染参数)的3元组,而不是(值、标签)的2元组

为第一个
选项
标记输出以下内容:

<option disabled="disabled" selected ...

作为Mark答案的替代方案,这里有一个自定义小部件(即“渲染器”字段),允许在渲染时传递选项属性

从markupsafe导入标记
从wtforms.widgets.core导入html_参数
类自定义选择:
"""
呈现允许选项的自定义属性的选择字段。
期望该字段是选项字段的iterable对象。
render函数接受选项id的字典(“{field_id}-{option_index}”)
其中包含要传递给选项的属性字典。
例子:
form.customselect(option_attr={“customselect-0”:{“disabled”:“}})
"""
def uuu init uuu(self,multiple=False):
self.multiple=多个
定义调用(self,field,option_attr=None,**kwargs):
如果选项_attr为无:
选项_attr={}
kwargs.setdefault(“id”,field.id)
如果self.multiple:
kwargs[“多个”]=真
如果kwargs中没有“必需”且getattr(字段,“标志”,[])中有“必需”:
kwargs[“必需”]=真
html=[“”%html_参数(name=field.name,**kwargs)]
对于字段中的选项:
attr=option\u attr.get(option.id,{})
html.append(选项(**attr))
html.append(“”)
返回标记(“.join(html))
声明字段时,将
CustomSelect
的实例作为
小部件
参数传递

customselect=SelectField(
“自定义选择”,
选项=[(“选项1”、“选项1”),(“选项2”、“选项2”)],
widget=CustomSelect(),
)
调用要呈现的字段时,传递选项id的字典(“{field_id}-{option_index}”),该字典定义要传递给选项的属性字典

form.customselect(option_attr={"customselect-0": {"data-id": "value"} })

签出这篇文章-我想你已经总结过了。@nsfyn55谢谢你的确认。我非常感谢。因为你知道它现在是如何工作的,而且有几个人想这样做。你甚至可以考虑将一个补丁提交给<代码> WTFrass Proj.@ NSfY55,你可以在这里看到整个NUVO:有趣的是,谢谢你的研究!这就是我一直在寻找的解决方案。谢谢,伙计。@jibinmath,这是否有效?在
SelectField.pre_validate()
(枚举选项时)中,我得到了太多要解包的值(预期为2)。这是关于
WTForms-2.1
(这是旧的…)的好观点-我错过了预验证覆盖。我已经更新了答案。@NealGokli你有解决方案吗?@jibinmathew我没有,但是试试上面马克的编辑!我决定我不需要它来做我正在做的事情,但我可能很快就要用它来做别的事情了!您实际上如何修改表单以集成这些额外选项?
from wtforms.fields  import SelectField
from wtforms.widgets import Select, html_params, HTMLString

class AttribSelect(Select):
    """
    Renders a select field that supports options including additional html params.

    The field must provide an `iter_choices()` method which the widget will
    call on rendering; this method must yield tuples of
    `(value, label, selected, html_attribs)`.
    """

    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, html_attribs in field.iter_choices():
            html.append(self.render_option(val, label, selected, **html_attribs))
        html.append('</select>')
        return HTMLString(''.join(html))

class AttribSelectField(SelectField):
    widget = AttribSelect()

    def iter_choices(self):
        for value, label, render_args in self.choices:
            yield (value, label, self.coerce(value) == self.data, render_args)

    def pre_validate(self, form):
         if self.choices:
             for v, _, _ in self.choices:
                 if self.data == v:
                     break
             else:
                 raise ValueError(self.gettext('Is Not a valid choice'))
choices = [('', 'select a name', dict(disabled='disabled'))]
choices.append(('alex', 'Alex', dict()))
select_field = AttribSelectField('name', choices=choices, default='')
<option disabled="disabled" selected ...
form.customselect(option_attr={"customselect-0": {"data-id": "value"} })