Created
November 16, 2012 14:01
-
-
Save Ignas/4087573 to your computer and use it in GitHub Desktop.
Simple formencode based form library for mako templates
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import formencode | |
from formencode import htmlfill, variabledecode | |
from webhelpers.html.builder import literal | |
from zope.cachedescriptors.property import Lazy | |
class FormEncodeState(object): | |
def __init__(self, request): | |
self.request = request | |
def error_formatter(message): | |
return '<div class="error-message">%s</div>' % message | |
class FormBase(object): | |
def __init__(self, context, request): | |
self.request = request | |
self.context = context | |
self.errors = {} | |
def validate_schema(self, schema, variable_decode=True, | |
dict_char='.', list_char='-'): | |
if variable_decode: | |
decoded = variabledecode.variable_decode(self.request.params, dict_char, list_char) | |
errors = {} | |
form_result = {} | |
try: | |
form_result = schema.to_python(decoded, | |
FormEncodeState(self.request)) | |
except formencode.Invalid, e: | |
errors = e.unpack_errors(variable_decode, dict_char, list_char) | |
return form_result, errors | |
def work(self): | |
if self.action in self.request.params: | |
values, errors = self.validate | |
if not errors: | |
return self.apply(self.context, values) | |
else: | |
self.errors = errors | |
def defaults(self): | |
return {} | |
def defaults_from_request(self, request): | |
return request.params | |
# XXX solving double validation using Lazy | |
@Lazy | |
def validate(self): | |
return self.validate_schema(self.schema) | |
def __call__(self, form_content): | |
# Defaults can be given either in a dict or a callable | |
defaults = self.defaults() if hasattr(self.defaults, '__call__') else self.defaults | |
errors = {} | |
if self.action in self.request.params: | |
_, errors = self.validate | |
defaults = self.defaults_from_request(self.request) | |
return literal(htmlfill.render(form_content, | |
defaults=defaults, | |
auto_error_formatter=error_formatter, | |
errors=errors)) | |
class Form(FormBase): | |
"""Class for one form views. | |
To define a form do something like in __init__ of the view: | |
>> self.form = Form(context, request, | |
.. apply=self.apply, | |
.. defaults=self.defaults, | |
.. schema=FormSchema(), | |
.. action='UPDATE') | |
""" | |
def apply(self, context, values): | |
return values | |
def __init__(self, context, request, schema, action, apply=None, defaults=None): | |
self.request = request | |
self.context = context | |
self.schema = schema | |
if apply is not None: | |
self.apply = apply | |
self.action = action | |
if defaults is not None: | |
self.defaults = defaults | |
""" | |
Add this to your base.mako | |
<%def name="form(filler)"> | |
${filler(capture(caller.body))} | |
</%def> | |
if you pass your form as add_form into in template context you can do | |
this: | |
<%self:form filler="${add_form}"> | |
<form method="post"> | |
<input type="text" name="title" /> | |
<input type="submit" name="ADD" value="Add" /> | |
</form> | |
</%self:form> | |
""" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
def my_view(request):
location = request.context
form = Form(location, request,
schema=SubDepartmentAddForm(),
action='ADD')