2013-01-24 97 views
7

WTForms文档极其不足,他们甚至不会向您显示一个不是从其他小部件派生的自定义小部件的单个示例。WTForms创建自定义小部件

我试图让一个按钮类型,即不是“输入”,以html:

提交= InlineButton(NAME =“提交”,类型=“提交”,标题='保存此页”,textWithinSpan = '保存')

from flask.ext.wtf import Required, Length, EqualTo, Field, TextInput, html_params 
from flask import Markup 

class InlineButtonWidget(object): 
    text = '' 
    html_params = staticmethod(html_params) 

    def __init__(self, input_type='submit', **kwargs): 
    self.input_type = input_type 

    def __call__(self, field, **kwargs): 
    kwargs.setdefault('id', field.id) 
    kwargs.setdefault('type', self.input_type) 
    if 'value' not in kwargs: 
     kwargs['value'] = field._value() 
    return Markup('<button type="submit" %s><span>%s</span></button>' % (self.html_params(name=field.name, **kwargs), kwargs['textWithinSpan'])) 


class InlineButton(Field): 
    widget = InlineButtonWidget() 

    def __init__(self, label='', **kwargs): 
    self.widget = InlineButtonWidget('submit', label) 
    def __call__(self, **kwargs): 
    return self.widget(self, **kwargs) 
    def _value(self): 
    if self.data: 
     return u', '.join(self.data) 
    else: 
     return u'' 


class SignupForm(Form): 
    name = TextField('Name', [Length(min=1, max=200)]) 
    submit = InlineButton(name='submit', type='submit', title='Save this page', textWithinSpan='Save') 

我不应该甚至需要现场派生对象。但是,当您仅使用Widget时,它不会显示。

而当你使用Field对象时,它会给你各种无效的参数错误。

即使深入研究WTForms源代码,也很难理解为什么它不会将Kwargs从窗体传递给窗口小部件。

--- UPDATE ---

好吧,以后我提出我基本上想出一个可行的解决方案的问题:

class InlineButtonWidget(object): 
    html_params = staticmethod(html_params) 

    def __init__(self, input_type='submit', text=''): 
     self.input_type = input_type 
     self.text = text 

    def __call__(self, field, **kwargs): 
     kwargs.setdefault('id', field.id) 
     kwargs.setdefault('type', self.input_type) 
     if 'value' not in kwargs: 
      kwargs['value'] = field._value() 
     return Markup('<button type="submit" %s><span>%s</span></button>' % (self.html_params(name=field.name, **kwargs), field.text)) 


class InlineButton(Field): 
    widget = InlineButtonWidget() 

    def __init__(self, label=None, validators=None, text='Save', **kwargs): 
    super(InlineButton, self).__init__(label, validators, **kwargs) 
    self.text = text 

    def _value(self): 
     if self.data: 
      return u''.join(self.data) 
     else: 
      return u'' 



class SignupForm(Form): 
    name = TextField('Name', [Length(min=1, max=200)]) 
    submit = InlineButton('submit', text='Save', description='Save this') 

回答

3

下更新回答,但我需要这个初始化场内衍生类。

def __init__(self, label=None, validators=None, text='Save', **kwargs): 
    super(InlineButton, self).__init__(label, validators, **kwargs) 
    self.text = text 
4

您可以利用该字段的有用属性,即'description'和'label'。这产生了更简单的设置:

from wtforms.widgets.core import HTMLString, html_params, escape 

class InlineButtonWidget(object): 
    def __call__(self, field, **kwargs): 
     kwargs.setdefault('type', 'submit') 
     # Allow passing title= or alternately use field.description 
     title = kwargs.pop('title', field.description or '') 
     params = html_params(title=title, **kwargs) 

     html = '<button %s><span>%s</span></button>' 
     return HTMLString(html % (params, escape(field.label.text))) 

用途:(为了便于阅读)

class MyForm(Form): 
    foo = BooleanField(
     u'Save', 
     description='Click here to save', 
     widget=InlineButtonWidget() 
    ) 

交替,具有用于它的字段类型:

class InlineButtonField(BooleanField): 
    widget = InlineButtonWidget() 

class MyForm(Form): 
    foo = InlineButtonField('Save', description='Save Me')