2013-01-24 13 views
7

Dokumentacja WTForms jest żałośnie niewystarczająca, nie pokazują nawet jednego przykładu niestandardowego widgetu, który nie jest już wyprowadzony z innego widgetu.WTForms tworzenie niestandardowego widżetu

Próbuję dokonać typ przycisku, który nie jest "wejście" w html:

submit = InlineButton (name = 'submit' type = 'submit' title = "Wyślij tę stronę ”textWithinSpan = 'Zapisz')

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') 

nie powinny mieć nawet polowy pochodzi przedmiot. Ale nie wyświetla się, gdy używasz tylko Widget sam.

A kiedy użyjesz obiektu Field, wtedy otrzymasz różnego rodzaju nieprawidłowe błędy parametrów.

Nawet zagłębianie się w kod źródłowy WTForms utrudnia zrozumienie, dlaczego nie przejdzie ono od formularza do widgetu.

--- UPDATE ---

Ok, po przesłać mi na pytanie I w zasadzie zorientowali się realne rozwiązanie:

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') 

Odpowiedz

3

Odpowiedział pod Update, ale potrzebne to Init wewnątrz Pole pochodzi klasa.

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

Możesz skorzystać z użytecznych atrybutów na tym polu, a mianowicie "opis" i "etykieta" dla tego wystąpienia. Daje to znacznie prostszą konfigurację:

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))) 

Zastosowanie: (zawinięte dla czytelności)

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

na przemian, aby mieć typ pola dla niej:

class InlineButtonField(BooleanField): 
    widget = InlineButtonWidget() 

class MyForm(Form): 
    foo = InlineButtonField('Save', description='Save Me') 
Powiązane problemy