2013-01-24 95 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')