I'm sorry for such long time without any reply, but I was investigating 
possible
approaches of mixing Django and Jinja2 templates.

On Sunday, February 16, 2014 1:08:49 AM UTC+1, Russell Keith-Magee wrote:
>
>
> On Sun, Feb 16, 2014 at 12:43 AM, Christopher Medrela <[email protected]
> > wrote:
>
>> My last post was pretty long and the most important questions and 
>> statements
>> have left unanswered, so I will repeat them.
>>
>> What I'm proposing now is more conservative proposal. Firstly, Django will
>> support Jinja2 out-of-the-box, but DTL will remain the "blessed" option.
>>
>
> As a broad statement, this sounds fine; but what does this mean in 
> practice? What does "out of the box" support look like?
>

The two main principles would be: 1) reusing existing interfaces and 
contracts
2) making switching from Djinja/jingo/django-jinja/coffin as easy as 
possible.

Last month, Djinja and jingo were downloaded 650 times while coffin and
django-jinja have each one 2k downloads. Coffin focus on imitating DTL.
Therefore, the "out of box" support should be similar to django-jinja.

Basically, the same functions will apply to Jinja2 as well as to Django
templates. If you want to render a template, you write
``render_to_response(template_name)``, whether the template is Jinja2 or 
Django
template. Templates will be distinguished by extension.

How can it be achieved?

 - We need to move all existing functions (like `render_to_response`) from
   django.template to a new module. Let's call it `django.dtl`.

 - Then, we can create dummy implementations of `render_to_response` (and 
all
   other functions) that checks the template extension and dispatch to
   corresponding function from `django.dtl` or `jinja2`.

 - It would be nice to use the same loaders for both django.dtl and jinja2. 
This
   requires to rewrite existing Django loaders so that they fulfill the 
contract
   of `jinja2.Loader`. 

Secondly, Django will allow to mix DTL and Jinja2 templates (so you can
>> include/inherit DTL template from Jinja2 one and vice versa).
>
>
> Including doesn't sound like it would be any problem, but inheriting? Is 
> that really going to be possible?


It seems to be possible. Consider parent Jinja2 template:

    Parent
    {% block overridden %}parent overridden block{% endblock %}
    {% block nonoverridden %}parent nonoverridden block{% endblock %}

as well as child Jinja2 template:

    {% extends "parent.jinja2" %}
    {% block overridden %}child overridden block{% endblock %}

Jinja2 compiles templates by generating valid Python code and passing it to
`exec` function. The appropriate code for the former is:

    from __future__ import division
    from jinja2.runtime import LoopContext, TemplateReference, Macro, 
Markup, TemplateRuntimeError, missing, concat, escape, markup_join, 
unicode_join, to_string, identity, TemplateNotFound
    name = 'parent'

    def root(context, environment=environment):
        if 0: yield None
        yield u'Parent '
        for event in context.blocks['overridden'][0](context):
            yield event
        for event in context.blocks['nonoverridden'][0](context):
            yield event

    def block_nonoverridden(context, environment=environment):
        if 0: yield None
        yield u'parent nonoverridden block'

    def block_overridden(context, environment=environment):
        if 0: yield None
        yield u'parent overridden block'

    blocks = {'nonoverridden': block_nonoverridden, 'overridden': 
block_overridden}
    debug_info = '1=8'

and for the child is:

    from __future__ import division
    from jinja2.runtime import LoopContext, TemplateReference, Macro, 
Markup, TemplateRuntimeError, missing, concat, escape, markup_join, 
unicode_join, to_string, identity, TemplateNotFound
    name = 'child'

    def root(context, environment=environment):
        parent_template = None
        if 0: yield None
        parent_template = environment.get_template('parent.jinja2', 'child')
        for name, parent_block in parent_template.blocks.iteritems():
            context.blocks.setdefault(name, []).append(parent_block)
        for event in parent_template.root_render_func(context):
            yield event

    def block_overridden(context, environment=environment):
        if 0: yield None
        yield u'child overridden block'

    blocks = {'overridden': block_overridden}
    debug_info = '1=8'

As you can see, child template loads parent template using
`environment.get_template` method; then iterates over its blocks; finally
delegates to it by calling `root_render_func` and passing the context.

We can write Jinja2 loader that checks the template extension; if it's 
"jinja2",
it delegates to another loader that is responsible for loading Jinja2 
templates;
otherwise, it loads appropriate Django template and wraps it with an 
adapter.
The adapter must have the same interface as `jinja2.Template` -- probably 
only
`blocks` and `root_render_func` need to be implemented. `root_render_func` 
will
be similar to `Template.render` and `blocks` is a map from block names to
functions rendering these blocks (these functions will be similar to
`BlockNode.render`). We also need to tamper with `BlockNode.render` method 
in
the case when the child template is DTL and the parent is written in Jinja2 
so
BlockNode can pass control to the block defined in parent template.

As I see it, there are three possible options here:
>
 

 1) Add Jinja2 as a supported option, but stick with DTL as the default.
>  2) Add Jinja2 as a supported option, and indicate that long term, we're 
> going to switch to Jinja as the default
>  3) Add Jinja2 as a supported option and move to it immediately as the 
> default.
>
 

My personal preferences would be in that order. This is something where 
> historically, we would have gone to the BDFLs for a call; I suspect the 
> core team might need to have a quick discussion and make a call, lest this 
> turn into the mother of all bike sheds.


First option is a necessary condition for the others and it seems to be big
enough GSoC project, therefore I will focus on it. In the future, if we 
changed
mind, we could move to other options. 

On Sunday, February 16, 2014 11:44:52 PM UTC+1, Donald Stufft wrote:
>
> On Feb 16, 2014, at 4:23 PM, Carl Meyer <[email protected]> wrote: 
>
> 

>> 2) Jinja2 doesn't support 3.2. Will Django 1.8 support 3.2? 
> > 
> > Donald might be able to offer better hard numbers based on e.g. PyPI 
> > usage, but my impression is that usage of 3.2 is very low, and dropping 
> > it for 1.8 would not be a major problem. 
>
> These numbers are about a month old, but 
> https://gist.github.com/dstufft/8455306 
>

Thank you very much, Donald! In short, the numbers are:

2.7 -- 6450k total downloads
3.2 --   60k
3.3 --  250k

It seems like the support for Python 3.2 could be dropped. 

>

-- 
You received this message because you are subscribed to the Google Groups 
"Django developers" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/django-developers.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/django-developers/ae007cb9-5219-4a57-bb03-77f5ee58f1e1%40googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Reply via email to