-
-
Save Kroisse/5343856 to your computer and use it in GitHub Desktop.
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
__pycache__/ | |
*.pyc |
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
"""Jinja2 x htmlfill | |
Known bugs: Can't skip empty dictionaries when htmlfilling is not needed. | |
# AUTHOR: HYUNJUN KIM <[email protected]> | |
# LICENSE: Distributed under MIT License. | |
""" | |
import formencode.htmlfill | |
import jinja2 | |
import jinja2.ext | |
import jinja2.nodes | |
class FormFillExtension(jinja2.ext.Extension): | |
"""Jinja2 Extension for convenient using of HTML ``<form>`` element. | |
Works with `FormEncode htmlfill`__ :: | |
{% formfill {'username': 'james'} | |
with {'username': 'Invalid Username'} %} | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" /> | |
<form:error name="username"> | |
<input type="password" name="password" /> | |
</form> | |
{% endformfill %} | |
Above code will be rendered like below :: | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" class="error" value="james" /> | |
<ul class="errors"><li>Invalid Username</li></ul> | |
<input type="password" name="password" value="" /> | |
</form> | |
__ http://www.formencode.org/en/latest/htmlfill.html | |
.. seealso:: | |
gist --- `formencode htmlfill in jinja2 template`__ | |
__ https://gist.github.com/4595277 | |
""" | |
tags = set(['formfill']) | |
def parse(self, parser): | |
lineno = parser.stream.next().lineno | |
defaults = parser.parse_expression() | |
errors = jinja2.nodes.Const({}) | |
name = parser.stream.next_if('name') | |
if name is not None: | |
if name.value == 'with': | |
errors = parser.parse_expression() | |
if isinstance(defaults, jinja2.nodes.Name): | |
defaults = jinja2.nodes.Getattr(jinja2.nodes.ContextReference(), | |
defaults.name, self.environment) | |
if isinstance(errors, jinja2.nodes.Name): | |
errors = jinja2.nodes.Getattr(jinja2.nodes.ContextReference(), | |
errors.name, self.environment) | |
body = parser.parse_statements(['name:endformfill'], drop_needle=True) | |
body = [jinja2.nodes.CallBlock( | |
self.call_method('_htmlfill_support', (defaults, errors)), | |
[], [], body).set_lineno(lineno)] | |
return body | |
def _htmlfill_support(self, defaults, errors, caller): | |
formatters = { | |
'default': lambda msg: u'<ul class="errors"><li>{0}</li></ul>' \ | |
.format(msg) | |
} | |
return formencode.htmlfill.render(caller(), defaults, errors, | |
error_formatters=formatters) |
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 pytest | |
import jinja2 | |
import htmlfill | |
@pytest.fixture | |
def jinja_env(): | |
env = jinja2.Environment(extensions=[htmlfill.FormFillExtension]) | |
return env | |
def test_formfill(jinja_env): | |
template = ''' | |
{% formfill {'username': 'james'} with {'username': 'Invalid Username'} -%} | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" /> | |
<form:error name="username"> | |
<input type="password" name="password" /> | |
</form> | |
{%- endformfill %}''' | |
expected = ''' | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" class="error" value="james" /> | |
<ul class="errors"><li>Invalid Username</li></ul> | |
<input type="password" name="password" value="" /> | |
</form>''' | |
result = jinja_env.from_string(template).render() | |
assert result == expected | |
def test_formfill_without_errors(jinja_env): | |
template = ''' | |
{% formfill {'username': 'james'} -%} | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" /> | |
<form:error name="username"> | |
<input type="password" name="password" /> | |
</form> | |
{%- endformfill %}''' | |
expected = ''' | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" value="james" /> | |
<input type="password" name="password" value="" /> | |
</form>''' | |
result = jinja_env.from_string(template).render() | |
assert result == expected | |
def test_formfill_without_args(jinja_env): | |
template = ''' | |
{% formfill -%} | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" /> | |
<input type="password" name="password" /> | |
</form> | |
{%- endformfill %}''' | |
template2 = ''' | |
{% formfill {'username': 'james'} with -%} | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" /> | |
<input type="password" name="password" /> | |
</form> | |
{%- endformfill %}''' | |
with pytest.raises(jinja2.TemplateSyntaxError): | |
jinja_env.from_string(template).render() | |
with pytest.raises(jinja2.TemplateSyntaxError): | |
jinja_env.from_string(template2).render() | |
def test_formfill_with_wrong_args(jinja_env): | |
template = ''' | |
{% formfill 'user.signin' -%} | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" /> | |
<input type="password" name="password" /> | |
</form> | |
{%- endformfill %}''' | |
with pytest.raises(AttributeError) as exc: | |
jinja_env.from_string(template).render() | |
assert "'str' object has no attribute 'get'" in str(exc) | |
template2 = ''' | |
{% formfill {'username': 'james'} with ['Invalid Username'] -%} | |
<form action="u/signin" method="POST"> | |
<input type="text" name="username" /> | |
<input type="password" name="password" /> | |
</form> | |
{%- endformfill %}''' | |
with pytest.raises(AttributeError) as exc: | |
jinja_env.from_string(template2).render() | |
assert "'list' object has no attribute 'get'" in str(exc) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment