From 3383e1ca375290d2cd248c11171ff7e5a2b92a4d Mon Sep 17 00:00:00 2001 From: Armin Ronacher Date: Mon, 24 Jan 2011 01:13:51 +0100 Subject: [PATCH] join now also accepts parameters --- CHANGES | 3 +++ jinja2/filters.py | 14 +++++++++++++- jinja2/nodes.py | 1 + jinja2/runtime.py | 1 - jinja2/testsuite/filters.py | 7 +++++++ 5 files changed, 24 insertions(+), 2 deletions(-) diff --git a/CHANGES b/CHANGES index 7cda7b2..2cdedf4 100644 --- a/CHANGES +++ b/CHANGES @@ -29,6 +29,9 @@ Version 2.6 optional starting index which defaultes to zero. This now became the second argument to the function because it's rarely used. - like sum, sort now also makes it possible to order items by attribute. +- like sum and sort, join now also is able to join attributes of objects + as string. +- the internal eval context now has a reference to the environment. Version 2.5.5 ------------- diff --git a/jinja2/filters.py b/jinja2/filters.py index 8cd8387..fe33eb0 100644 --- a/jinja2/filters.py +++ b/jinja2/filters.py @@ -256,7 +256,7 @@ def do_default(value, default_value=u'', boolean=False): @evalcontextfilter -def do_join(eval_ctx, value, d=u''): +def do_join(eval_ctx, value, d=u'', attribute=None): """Return a string which is the concatenation of the strings in the sequence. The separator between elements is an empty string per default, you can define it with the optional parameter: @@ -268,7 +268,19 @@ def do_join(eval_ctx, value, d=u''): {{ [1, 2, 3]|join }} -> 123 + + It is also possible to join certain attributes of an object: + + .. sourcecode:: jinja + + {{ users|join(', ', attribute='username') }} + + .. versionadded:: 2.6 + The `attribute` parameter was added. """ + if attribute is not None: + value = imap(make_attrgetter(eval_ctx.environment, attribute), value) + # no automatic escaping? joining is a lot eaiser then if not eval_ctx.autoescape: return unicode(d).join(imap(unicode, value)) diff --git a/jinja2/nodes.py b/jinja2/nodes.py index c18d299..f9da1da 100644 --- a/jinja2/nodes.py +++ b/jinja2/nodes.py @@ -77,6 +77,7 @@ class EvalContext(object): """ def __init__(self, environment, template_name=None): + self.environment = environment if callable(environment.autoescape): self.autoescape = environment.autoescape(template_name) else: diff --git a/jinja2/runtime.py b/jinja2/runtime.py index 72ab93e..d73483d 100644 --- a/jinja2/runtime.py +++ b/jinja2/runtime.py @@ -8,7 +8,6 @@ :copyright: (c) 2010 by the Jinja Team. :license: BSD. """ -import sys from itertools import chain, imap from jinja2.nodes import EvalContext, _context_function_types from jinja2.utils import Markup, partial, soft_unicode, escape, missing, \ diff --git a/jinja2/testsuite/filters.py b/jinja2/testsuite/filters.py index 64cd0a9..ff04c9f 100644 --- a/jinja2/testsuite/filters.py +++ b/jinja2/testsuite/filters.py @@ -128,6 +128,13 @@ class FilterTestCase(JinjaTestCase): tmpl = env2.from_string('{{ ["", "foo"|safe]|join }}') assert tmpl.render() == '<foo>foo' + def test_join_attribute(self): + class User(object): + def __init__(self, username): + self.username = username + tmpl = env.from_string('''{{ users|join(', ', 'username') }}''') + assert tmpl.render(users=map(User, ['foo', 'bar'])) == 'foo, bar' + def test_last(self): tmpl = env.from_string('''{{ foo|last }}''') out = tmpl.render(foo=range(10)) -- 2.26.2