--- /dev/null
+^instance$
+^instance/
+^jinja/.*\.so$
+^(build|dist|Jinja\.egg-info)/
+\.py[co]$
+\.DS_Store$
Version 1.2
-----------
-(codename to be selected, release date unknown)
+(codename to be hatsuyuki, released Nov 17th 2007)
+
+.. admonition:: Backwards Incompatible Changes
+
+ - `call` is a keyword now
+ - the internal parser AST changed
+ - `extends` must be the first tag in a template
+ - the tuple literal yields tuples now, instead of lists.
- environments now have a `translator_factory` parameter that allows
to change the translator without subclassing the environment.
templates. Although the import system was implemented three Python versions
ago the default traceback system still doesn't support it.
-However most of the extended web development traceback module support it:
+However most of the extended web development traceback modules have support
+for `__loader__`. Either directly or via the linecache module:
-- `Colubrid Debugging Middleware`_
+- `Werkzeug Debugging Middleware`_
+- `Django`_
- `cgitb`_
- `EvalException`_
-Note that the django traceback module currently does not provide this. `A
-ticket`_ was filed already so there is hope that this will be fixed.
-
To enable debugging you have to use one of those debugging systems or
implement your own one with support for `__loader__`.
+The python implementation of the jinja debugger can only translate the first
+exception in a traceback which can lead to problematic results. If you have
+the extended debugger c extension compiled (default on unix systems but only
+available on Windows if you have a VisualStudio 2003 installation) all frames
+in the traceback will point to the correct linenumbers of the templates.
+
-.. _Colubrid Debugging Middleware: http://trac.pocoo.org/repos/colubrid/trunk/colubrid/debug.py
+.. _Werkzeug Debugging Middleware: http://werkzeug.pocoo.org/
+.. _Django: http://www.djangoproject.com/
.. _cgitb: http://docs.python.org/lib/module-cgitb.html
.. _EvalException: http://pythonpaste.org/module-paste.evalexception.html
-.. _A ticket: http://code.djangoproject.com/ticket/3734
``undefined`` special Jinja undefined singleton.
======================= ===================================================
+.. admonition:: Common Pitfalls
+
+ Keep in mind that Jinja literals, keywords and functions are all lowercase.
+ If you're used to Python you probably tried to write `True` which evaluates
+ to undefined because it simply does not exist. The correct name for the
+ true value is just `true` (lowercase).
+
+
Operators
=========
In the template you can now access the local variables `seq` and `foo`.
+
Using Django Filters with Jinja
===============================
Also keep in mind that Jinja knows about keywords, thus you cannot have a filter
that is called `pluralize` for example.
+Such a conversion function is also part of the djangosupport module which was
+introduced in Jinja 1.2. It's explained on the `Framework Integration`_ page.
+
Using Jinja in Django
=====================
+.. admonition:: Note
+
+ This section is more or less obsolete as of Jinja 1.2 which provides a
+ djangosupport module, covered on the `Framework Integration`_ page.
+
This snippet was contributed by Bryan McLemore. It provides a `render_to_response`
function similar to the one shipped with django just that it uses Jinja for
rendering. It applies the context processors on the context and consumes a
Because Django uses gettext internally we can create just assign the
ngettext and gettext functions directly to the translator class.
+
+
+.. _Framework Integration: frameworks.txt
Starting with `Jinja 1.1` you can also handle some whitespace rules in the
template. If you put an minus sign (`-`) to the start or end of an block
-(for example a `for` tag) or a comment, variable element you can remove
-the whitespaces after that block or before that block:
+(for example a `for` tag), a comment or variable element you can remove
+the whitespaces after or before that block:
.. sourcecode:: jinja
framework so far. This specification however tries to solve the problems that
exist in Buffet.
+
Buffet
======
The `downloads` action uses the pylons specific leading foreslash notation.
+
General Template Interface
==========================
Using Jinja in django is straightforward because django has a pretty low
level response interface. Just have a look at the `developer recipies`_,
-there are some examples for django.
+there are some examples for django. Starting with Jinja 1.2 there is also
+a contrib module that simplifies using Jinja in an unicode enabled django.
+
+Quickstart
+----------
+
+To get started execute the following code at the bottom of your settings.py
+or in some general application file such as urls.py or a central module. The
+only thing that matters is that it's executed right *after* the settings
+were set up and *before* `django.contrib.jinja` is imported::
+
+ from jinja.contrib import djangosupport
+ djangosupport.configure()
+
+What this does is setting up a Jinja environment for this django instance
+with loaders for `TEMPLATE_DIRS` etc. It also converts a couple of default
+django filters such as `date` and `timesince` which are not available in
+Jinja per default. If you want to change the list you can provide others
+by passing a list with filter import names as `convert_filters` keyword
+argument.
+
+All other keyword arguments are forwarded to the environment. If you want
+to provide a loader yourself pass it a loader keyword argument.
+
+Rendering Templates
+-------------------
+
+To render a template you can use the functions `render_to_string` or
+`render_to_response` from the `django.contrib.jinja` module::
+
+ from django.contrib.jinja import render_to_response
+ resp = render_to_response('Hello {{ username }}!', {
+ 'username': req.session['username']
+ }, req)
+
+`render_to_string` and `render_to_response` take at least the name of
+the template as argument, then the optional dict which will become the
+context. If you also provide a request object as third argument the
+context processors will be applied.
+
+`render_to_response` also takes a forth parameter which can be the
+content type which defaults to `DEFAULT_CONTENT_TYPE`.
+
+Converting Filters
+------------------
+
+One of the useful objects provided by `django.contrib.jinja` is the
+`register` object which can be used to register filters, tests and
+global objects. You can also convert any filter django provides in
+a Jinja filter using `convert_django_filter`::
+
+ from django.contrib.jinja import register, convert_django_filter
+ from django.template.defaultfilters import floatformat
+
+ register.filter(convert_django_filter(floatformat), 'floatformat')
+
+Available methods on the `register` object:
+
+``object (obj[, name])``
+ Register a new global as name or with the object's name.
+ Returns the function object unchanged so that you can use
+ it as decorator if no name is provided.
+
+``filter (func[, name])``
+ Register a function as filter with the name provided or
+ the object's name as filtername.
+ Returns the function object unchanged so that you can use
+ it as decorator if no name is provided.
+
+``test (func[, name])``
+ Register a function as test with the name provided or the
+ object's name as testname.
+ Returns the function object unchanged so that you can use
+ it as decorator if no name is provided.
+
+``context_inclusion (func, template[, name])``
+ Register a function with a name provided or the func object's
+ name in the global namespace that acts as subrender function.
+
+ func is called with the callers context as dict and the
+ arguments and keywords argument of the inclusion function.
+ The function should then process the context and return a
+ new context or the same context object. Afterwards the
+ template is rendered with this context.
+
+ Example::
+
+ def add_author(context, author=None):
+ if author is not None:
+ author = Author.objects.get(name=author)
+ context['author'] = author
+ return context
+
+ register.context_inclusion(add_author, 'author_details.html',
+ 'render_author_details')
+
+ You can use it in the template like this then::
+
+ {{ render_author_details('John Doe') }}
+
+``clean_inclusion (func, template[, name[, run_processors]]) ``
+ Works like `context_inclusion` but doesn't use the calles
+ context but an empty context. If `run_processors` is `True`
+ it will lookup the context for a `request` object and pass
+ it to the render function to apply context processors.
+
.. _Pylons: http://www.pylonshq.com/
Jinja requires at least Python 2.3 to work correctly.
+
Installing a released version
=============================
This will install Jinja into your Python installation's site-packages directory.
+
Installing the development version
==================================
4. ``ln -s jinja /usr/lib/python2.X/site-packages``
As an alternative to steps 4 you can also do ``python setup.py develop``
-which will install the package via setuptools in development mode.
+which will install the package via setuptools in development mode. This also
+has the advantage that the c extensions are compiled.
If you just want the latest features and use them
-------------------------------------------------
in your Python installation's site-packages directory. Every time the command
is run, the sources are updated from Subversion.
+
+Windows Installation Information
+================================
+
+On windows computers without Visual Studio 2003 Jinja is unable to compile the
+C extensions. This is usually not a problem because there is a fallback for
+native Python implementations of those C libraries. However under certain
+conditions the installation may fail with an error message. In that case try
+to disable the extensions by passing the following parameters to setup.py::
+
+ python setup.py install --without-speedups --without-extended-debugger
+
+
Documentation
=============
After the iteration `last_item` will point to the item of the last iteration.
-If `last_item` was not defined in the outer scope it wouldn't exist now because
-in that situation `set`, even with a postfixed bang just behaves like setting a
-scope variable.
+If `last_item` was not defined in the outer scope it would be defined in the
+outermost scope.
if name in layer:
layer[name] = value
return
- self.current[name] = value
+ self.initial[name] = value
def translate_func(self):
"""
features={
'speedups': Feature(
'optional C-speed enhancements',
- standard = True,
- ext_modules = [
+ standard=True,
+ ext_modules=[
Extension('jinja._speedups', ['jinja/_speedups.c'])
]
),
'extended-debugger': Feature(
'extended debugger',
- standard = True,
- ext_modules = [
+ standard=True,
+ ext_modules=[
Extension('jinja._debugger', ['jinja/_debugger.c'])
]
)
:copyright: 2007 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
+from jinja import Environment
+
+
+NONLOCALSET = '''\
+{% for item in range(10) %}
+ {%- set outer = item! -%}
+{% endfor -%}
+{{ outer }}'''
class PrivateStuff(object):
...
TemplateSyntaxError: cannot assign to expression (line 1)
'''
+
+
+def test_nonlocal_set():
+ env = Environment()
+ env.globals['outer'] = 42
+ tmpl = env.from_string(NONLOCALSET)
+ assert tmpl.render() == '9'
+ assert env.globals['outer'] == 42