Source code for formencode_jinja2.formfill

import collections
import formencode.htmlfill
import jinja2
import jinja2.ext
from jinja2 import nodes


__all__ = ['FormFillExtension']


[docs]class FormFillExtension(jinja2.ext.Extension): """Jinja2 extension for filling HTML forms via :mod:`formencode.htmlfill`. For example, this code: .. code-block:: html+jinja {% formfill {'username': 'robert', 'email': 'robert153@usrobots.com'} with {'username': 'This name is invalid'} %} <form action="/register" method="POST"> <input type="text" name="username" /> <form:error name="username"> <input type="password" name="password" /> <input type="email" name="email" /> </form> {% endformfill %} will be rendered like below: .. code-block:: html <form action="/register" method="POST"> <input type="text" name="username" class="error" value="robert" /> <span class="error-message">This name is invalid</span> <input type="password" name="password" value="" /> <input type="email" name="email" value="robert153@usrobots.com" /> </form> **Syntax:** .. code-block:: jinja {% formfill <defaults> [with <errors>] %} body {% endformfill %} :param defaults: a :term:`mapping` that contains default values of the input field (including ``select`` and ``textarea``) surrounded in the template tag. Keys contain a value of ``name`` attribute of the input field, and values contain its default value. :param errors: a :term:`mapping` that contains error messages of the input fields. this value will also effect ``class`` attribute of the input field. :returns: rendered forms This extension provides the additional variables in the Jinja2 environment: .. attribute:: jinja2.Environment.formfill_config The default rendering configuration of the ``formfill`` tag. This property accepts the same arguments of :func:`formencode.htmlfill.render`, except ``form``, ``defaults``, ``errors`` and ``error_formatters``. .. attribute:: jinja2.Environment.formfill_error_formatters The :term:`mapping` of error formatters and its name. Formatters are functions or callable objects that take the error text as a single argument, and returns a formatted text as a string. .. seealso:: http://www.formencode.org/en/latest/htmlfill.html#errors """ tags = frozenset(['formfill']) def __init__(self, environment): super(FormFillExtension, self).__init__(environment) environment.extend( formfill_config={}, formfill_error_formatters=dict(DEFAULT_ERROR_FORMATTERS), ) def parse(self, parser): token = next(parser.stream) defaults = parser.parse_expression() if parser.stream.skip_if('name:with'): errors = parser.parse_expression() else: errors = nodes.Const({}) body = parser.parse_statements(['name:endformfill'], drop_needle=True) return nodes.CallBlock( self.call_method('_formfill_support', [defaults, errors]), [], [], body).set_lineno(token.lineno) def _formfill_support(self, defaults, errors, caller): if isinstance(defaults, jinja2.runtime.Undefined): defaults = {} if isinstance(errors, jinja2.runtime.Undefined): errors = {} if not isinstance(defaults, collections.Mapping): raise TypeError("argument 'defaults' should be " "collections.Mapping, not {0!r}".format(defaults)) if not isinstance(errors, collections.Mapping): raise TypeError("argument 'errors' should be collections.Mapping, " "not {0!r}".format(errors)) rv = caller() return formencode.htmlfill.render( rv, defaults, errors, error_formatters=self.environment.formfill_error_formatters, **self.environment.formfill_config)
def default_formatter(error): """Escape the error, and wrap it in a span with class ``error-message``""" quoted = formencode.htmlfill.escape_formatter(error) return u'<span class="error-message">{0}</span>'.format(quoted) DEFAULT_ERROR_FORMATTERS = dict(formencode.htmlfill.default_formatter_dict) DEFAULT_ERROR_FORMATTERS.update( default=default_formatter, )