# #
###############################################################################
-from ..backend import forms
from . import base
-class _Form(object):
- def __init__(self, form):
+class Form(object):
+ def __init__(self, handler, method="POST", action="",
+ form=None, label=None, help=None, disabled=False):
+ self.handler = handler
+ self.method = method
+ self.action = action
self.form = form
- self._elements = []
+ self.label = label
+ self.help = help
+
+ self.elements = []
# Is this form disabled?
- self.disabled = False
+ self.disabled = disabled
def __iter__(self):
"""
Iterating over a form will iterate over its elements.
"""
- return iter(self._elements)
+ for element in self.elements:
+ yield element
- @property
- def parent_form(self):
- if self.form:
- return self.form.parent_form
+ if isinstance(element, Form):
+ for e in element:
+ yield e
+
+ def export(self):
+ """
+ Returns a dictionary with all keys and values
+ of the form.
+ """
+ ret = {}
- return self
+ for element in self:
+ # Skip any sub-form elements
+ if isinstance(element, Form):
+ continue
- @property
- def elements(self):
- for e in self._elements:
- if isinstance(e, _Form):
- for i in e._elements:
- yield i
+ ret[element.name] = element.value
+
+ return ret
+
+ # Sub-Forms
- else:
- yield e
+ def _add_subform(self, cls, *args, **kwargs):
+ form = cls(self.handler, *args, form=self, **kwargs)
+ self.elements.append(form)
- def _add_element(self, element):
+ return form
+
+ def add_group(self, *args, **kwargs):
+ return self._add_subform(Group, *args, **kwargs)
+
+ def add_fieldset(self, *args, **kwargs):
+ return self._add_subform(Fieldset, *args, **kwargs)
+
+ # Elements
+
+ def _add_element(self, cls, *args, **kwargs):
"""
Adds a new form element to this form.
"""
- assert isinstance(element, Element)
- assert not element in self.elements
-
- self._elements.append(element)
+ element = cls(self, *args, **kwargs)
+ self.elements.append(element)
- def _add_element_class(self, cls, *args, **kwargs):
- e = cls(self, *args, **kwargs)
- self._add_element(e)
-
- return e
+ return element
def get_element_by_name(self, name):
"""
Returns the element with the given name (if any).
"""
- for e in self.elements:
- if e.name == name:
- return e
+ for element in self:
+ if element.name == name:
+ return element
# Have a shortcut to find elements by their name quickly.
- get = get_element_by_name
+ __getattr__ = get_element_by_name
def add_text_input(self, *args, **kwargs):
"""
- Creates a new text input.
+ Creates a new text input
"""
- return self._add_element_class(TextInput, *args, **kwargs)
+ return self._add_element(TextInput, *args, **kwargs)
def add_multiline_text_input(self, *args, **kwargs):
"""
- Creates a new multiline text input.
+ Creates a new multiline text input
"""
- return self._add_element_class(MultilineTextInput, *args, **kwargs)
+ return self._add_element(MultilineTextInput, *args, **kwargs)
def add_password_input(self, *args, **kwargs):
"""
- Creates a new password input.
+ Creates a new password input
"""
- return self._add_element_class(PasswordInput, *args, **kwargs)
+ return self._add_element(PasswordInput, *args, **kwargs)
def add_yesno_input(self, *args, **kwargs):
"""
- Creates a new yes/no input.
+ Creates a new yes/no input
"""
- return self._add_element_class(YesNoInput, *args, **kwargs)
+ return self._add_element(YesNoInput, *args, **kwargs)
def add_single_choice_input(self, *args, **kwargs):
"""
- Creates a new single choice input.
+ Creates a new single choice input
"""
- return self._add_element_class(SingleChoiceInput, *args, **kwargs)
+ return self._add_element(SingleChoiceInput, *args, **kwargs)
def add_multiple_choice_input(self, *args, **kwargs):
"""
- Creates a new multiple choice input.
+ Creates a new multiple choice input
"""
- return self._add_element_class(MultipleChoiceInput, *args, **kwargs)
-
- def _get_value(self, *args, **kwargs):
- return self.parent_form._get_value(*args, **kwargs)
+ return self._add_element(MultipleChoiceInput, *args, **kwargs)
-class FormGroupMixin(object):
- def add_group(self, *args, **kwargs):
- group = Group(self, *args, **kwargs)
- self._elements.append(group)
-
- return group
-
-
-class Form(_Form, FormGroupMixin):
- def __init__(self, handler, method="POST", action=""):
- _Form.__init__(self, None)
- self.handler = handler
-
- self.method = method
- self.action = action
-
- # Text that is shown on the submit button
- self.submit_text = None
-
- def add_fieldset(self, *args, **kwargs):
- fs = Fieldset(self, *args, **kwargs)
- self._elements.append(fs)
-
- return fs
-
- def export(self):
- """
- Returns a dictionary with all keys and values
- of the form.
- """
- ret = {}
-
- for e in self.elements:
- ret[e.name] = e.value
-
- return ret
-
- def _get_value(self, name, default=None):
- return self.handler.get_argument(name, default)
-
-
-class Fieldset(_Form, FormGroupMixin):
- def __init__(self, *args, label=None, help=None, **kwargs):
- _Form.__init__(self, *args, **kwargs)
-
- self.label = label
- self.help = help
+class Fieldset(Form):
+ pass
class FormFieldsetModule(base.BaseUIModule):
return self.render_string("modules/forms/fieldset.html", fs=fieldset)
-class Group(_Form):
- def __init__(self, *args, label=None, **kwargs):
- _Form.__init__(self, *args, **kwargs)
-
- self.label = label
- self.help = None
+class Group(Form):
+ pass
class Element(object):
# The element type
type = None
- def __init__(self, form, name=None, label=None, default=None, **kwargs):
+ def __init__(self, form, name=None, label=None, default=None,
+ disabled=False, readonly=False, **kwargs):
assert self.type
self.form = form
self.default = default
# Is this element editable?
- self.disabled = False
- self.readonly = False
+ self.disabled = disabled
+ self.readonly = readonly
# Help text
self.help = None
- # Set defaults for inheriting classes
- self._set_defaults()
-
- # Set args
- for k, v in kwargs.items():
- setattr(self, k, v)
+ # Call initializer for inheriting classes
+ self.initialize(**kwargs)
- self.init(**kwargs)
-
- def _set_defaults(self):
- pass
-
- def init(self, *args, **kwargs):
+ def initialize(self):
pass
@property
"""
Returns the value that the user entered for this element.
"""
- return self.get_value()
-
- def get_value(self):
- return self.form._get_value(self.name, self.default)
+ return self.form.handler.get_argument(self.name, self.default)
class SingleChoiceInput(Element):
class FormModule(base.BaseUIModule):
def render(self, form):
- return self.render_string("modules/forms/index.html",
- f=form, forms=forms)
+ return self.render_string("modules/forms/index.html", form=form)
class FormElementsModule(base.BaseUIModule):
class TextInput(Element):
type = "text"
- def _set_defaults(self):
- self.prefix = None
- self.suffix = None
-
- self._placeholder = None
+ def initialize(self, prefix=None, suffix=None, placeholder=None):
+ self.prefix = prefix
+ self.suffix = suffix
- def get_placeholder(self):
- return self._placeholder or self.label
-
- def set_placeholder(self, placeholder):
- self._placeholder = placeholder
-
- placeholder = property(get_placeholder, set_placeholder)
+ self.placeholder = placeholder or self.label
class TextInputModule(base.BaseUIModule):
class MultilineTextInput(TextInput):
type = "multiline-text"
- def _set_defaults(self):
- TextInput._set_defaults(self)
+ DEFAULT_LINES = 3
+
+ def initialize(self, lines=DEFAULT_LINES, **kwargs):
+ super().initialize(**kwargs)
+
+ self.lines = lines
- # Default number of rows
- self.lines = 3
class MultilineTextInputModule(base.BaseUIModule):
class YesNoInput(Element):
type = "yesno"
- def _set_defaults(self):
- self.description = None
+ def initialize(self, description=None):
+ self.description = description
def get_value(self):
value = Element.get_value(self)