您的位置:首页 > 编程语言

自行编写代码解决 WTForm 无纯 Button 按钮的问题——button篇

2015-05-26 22:44 323 查看
在上一篇,我们已经了解到 WTForm 自带的元素的局限性,所以通过自定义的方式实现了一个
<input type='button' />
形式的按钮元素。在本篇中,我们就试着实现
<button type='button'>BUTTON</button>
形式的按钮。

之前的一篇里,我们所实现的按钮元素,其实与 WTForm 所提供的
SubmitField
没有本质上的区别,只是其
type
改变了,来源就是 WTForm 的源代码(
simple.py
文件)。而我们观察 WTForm 源代码的其他部分(
core.py
文件)发现,不光有一种实现形式,还有一种如下形式的元素类定义:

[code]class Label(object):
    """
    An HTML form label.
    """
    def __init__(self, field_id, text):
        self.field_id = field_id
        self.text = text

    # ... 中略 ...

    def __call__(self, text=None, **kwargs):
        if 'for_' in kwargs:
            kwargs['for'] = kwargs.pop('for_')
        else:
            kwargs.setdefault('for', self.field_id)

        attributes = widgets.html_params(**kwargs)
        return widgets.HTMLString('<label %s>%s</label>' % (attributes, text or self.text))

    def __repr__(self):
        return 'Label(%r, %r)' % (self.field_id, self.text)


那么这种继承自
object
的元素类,具有怎样一种特征呢?对比两个文件所定义的元素类对应的 HTML元素,可以发现一个规律:
simple.py
中主要定义了单标签式的 HTML元素——更准确的说——各种
<input />
标签的元素。直到最新版本,才增加了
TextAreaField
这一元素,其对应的 HTML元素为
<textarea></textarea>
simple.py
定义的元素类有如下几个:

[code]class TextField(StringField)      <input type='text' />
class TextAreaField(StringField)  <textarea></textarea>
class PasswordField(StringField)  <input type='password' />
class FileField(StringField)      <input type='file' />
class HiddenField(StringField)    <input type='hidden' />
class SubmitField(BooleanField)   <input type='submit' />


而另一面,
core.py
中所定义的元素则基本都为包裹式标签的HTML元素。那么,我们自然可以想到,要实现
<button></button>
元素,最可能的解决方案是参考
core.py
中的实现方式。

分析过程可以参考前一篇的思路,这里就不再重复,基本都是大同小异分析相似类的结构,剥离出与类本质相关的部分。这里我们直接给出实现代码。

[code]
from werkzeug.utils import escape, text_type
from wtforms import Field, Label
from wtforms.widgets import HTMLString, html_params

class ButtonWidget(object):
    '''
    用于显示 button 式按钮的部件(widget)
    '''

    def __call__(self, field, **kwargs):
        if field.name is not None:
            kwargs.setdefault('name', field.name)
        if field.value is not None:
            kwargs.setdefault('value', field.value)
        kwargs.setdefault('type', field.type)
        kwargs.setdefault('id', field.id)
        return HTMLString('<button %s>%s</button>' % (html_params(**kwargs), escape(field._value())))

class ButtonButtonField(Field):
    '''
    button式按钮
    '''
    widget = ButtonWidget()

    def __init__(self, bid=None, text=None, name=None, value=None, btype='button',label=None, **kwargs):
        """
        button式按钮构造函数
        :param bid: 按钮id——只在不使用 wtf.quick_form()时生效
        :param text: 按钮显示的文本
        :param name: 按钮的名称
        :param value: 按钮的初始值
        :param btype: submit/button/reset.
        :param label: 按钮前置Label——只在使用wtf.quick_form()时生效或使用 .label 方式强制
        """
        super(ButtonButtonField, self).__init__(**kwargs)
        if label is None:
            self.label = Label(field_id='Null', text='')
        else:
            self.label = Label(field_id=self.short_name, text=label)
        self.text = text
        self.value = value
        self.type = btype
        self.id = bid
        if name is not None:
            self.name = name

    def _value(self):
        return text_type(self.text)


以后要使用时,只需要直接
import ButtonButtonField
即可。

然而本篇并没哟结束,上一篇里曾提到如何规避使用 Jinja2模板引擎 渲染不正常的问题,其实很简单——不要使用
quick_form()
方法,而是改为手写
form.属性
的方式,搭配 CSS样式,一样可以实现非常棒的效果。大家抽空可以试一试。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐