Merge pull request #80 from jbalogh/extension

Move away from helpers, fix #75
This commit is contained in:
James Socol 2016-05-30 14:14:01 -04:00
commit 2c00f82b81
4 changed files with 36 additions and 26 deletions

View File

@ -106,15 +106,24 @@ If you want to configure the Jinja environment, use ``JINJA_CONFIG`` in
JINJA_CONFIG = {'autoescape': False}
or ::
or::
def JINJA_CONFIG():
return {'the_answer': 41 + 1}
If you set the ``extensions`` key in the configuration, you **must**
include ``jingo.ext.JingoExtension`` to get Jingo's built-in template
helpers (see below).
Template Helpers
----------------
.. note::
In the interest of future-proofing, consider writing custom filters and
functions as Jinja extensions. See ``jingo/ext.py`` for a simple example.
Instead of template tags, Jinja encourages you to add functions and filters to
the templating environment. In ``jingo``, we call these helpers. When the
Jinja environment is initialized, ``jingo`` will try to open a ``helpers.py``
@ -130,23 +139,18 @@ the environment extension:
Adds the decorated function to Jinja's global namespace.
.. highlight:: jinja
Default Helpers
~~~~~~~~~~~~~~~
Helpers are available in all templates automatically, without any extra
loading.
.. automodule:: jingo.helpers
:members:
loading. See ``jingo/ext.py`` for their definitions.
Template Environment
--------------------
A single Jinja ``Environment`` is created for use in all templates. This is
available as ``jingo.env`` if you need to work with the ``Environment``.
available via ``jingo.get_env()`` if you need to work with the ``Environment``.
Localization

View File

@ -132,7 +132,7 @@ def get_env():
opts = {
'trim_blocks': True,
'extensions': ['jinja2.ext.i18n'],
'extensions': ['jinja2.ext.i18n', 'jingo.ext.JingoExtension'],
'autoescape': True,
'auto_reload': settings.DEBUG,
'loader': jinja2.ChoiceLoader(loaders),
@ -181,8 +181,6 @@ def load_helpers():
return
_helpers_loaded = True
from jingo import helpers # noqa
for config in apps.get_app_configs():
if not has_helpers(config):
continue

View File

@ -20,18 +20,15 @@ from django.utils.http import urlencode
from django.utils.translation import ugettext as _
import jinja2
from jingo import register
from jinja2.ext import Extension
@register.function
@jinja2.contextfunction
def csrf(context):
"""Equivalent of Django's ``{% crsf_token %}``."""
return jinja2.Markup(CsrfTokenNode().render(context))
@register.filter
def f(s, *args, **kwargs):
"""
Uses ``str.format`` for string interpolation.
@ -41,11 +38,11 @@ def f(s, *args, **kwargs):
>>> {{ "{0} arguments and {x} arguments"|f('positional', x='keyword') }}
"positional arguments and keyword arguments"
"""
# TODO: Warning
s = six.text_type(s)
return s.format(*args, **kwargs)
@register.filter
def fe(s, *args, **kwargs):
"""Format a safe string with potentially unsafe arguments, then return a
safe string."""
@ -60,7 +57,6 @@ def fe(s, *args, **kwargs):
return jinja2.Markup(s.format(*args, **kwargs))
@register.filter
def nl2br(string):
"""Turn newlines into <br>."""
if not string:
@ -68,8 +64,7 @@ def nl2br(string):
return jinja2.Markup('<br>'.join(jinja2.escape(string).splitlines()))
@register.filter
def datetime(t, fmt=None):
def datetime_filter(t, fmt=None):
"""Call ``datetime.strftime`` with the given format string."""
if fmt is None:
fmt = _(u'%B %e, %Y')
@ -80,19 +75,16 @@ def datetime(t, fmt=None):
return smart_text(t.strftime(fmt)) if t else ''
@register.filter
def ifeq(a, b, text):
"""Return ``text`` if ``a == b``."""
return jinja2.Markup(text if a == b else '')
@register.filter
def class_selected(a, b):
"""Return ``'class="selected"'`` if ``a == b``."""
return ifeq(a, b, 'class="selected"')
@register.filter
def field_attrs(field_inst, **kwargs):
"""Adds html attributes to django form fields"""
for k, v in kwargs.items():
@ -106,13 +98,11 @@ def field_attrs(field_inst, **kwargs):
return field_inst
@register.function(override=False)
def url(viewname, *args, **kwargs):
"""Return URL using django's ``reverse()`` function."""
return reverse(viewname, args=args, kwargs=kwargs)
@register.filter
def urlparams(url_, fragment=None, query_dict=None, **query):
"""
Add a fragment and/or query parameters to a URL.
@ -144,3 +134,21 @@ names, which will be replaced.
new = urlparse.ParseResult(url_.scheme, url_.netloc, url_.path,
url_.params, query_string, fragment)
return new.geturl()
class JingoExtension(Extension):
def __init__(self, environment):
environment.globals.update({
'csrf': csrf,
'url': url,
})
environment.filters.update({
'class_selected': class_selected,
'datetime': datetime_filter,
'f': f,
'fe': fe,
'field_attrs': field_attrs,
'ifeq': ifeq,
'nl2br': nl2br,
'urlparams': urlparams,
})

View File

@ -15,7 +15,7 @@ except ImportError:
from mock import patch
from nose.tools import eq_
from jingo import helpers
from jingo import ext as helpers
from jingo import register
from .utils import htmleq_, render
@ -122,7 +122,7 @@ def test_datetime():
def test_datetime_unicode():
fmt = u"%Y 年 %m 月 %e"
helpers.datetime(datetime.now(), fmt)
helpers.datetime_filter(datetime.now(), fmt)
def test_ifeq():