Multiple template engines for Django - week 1

1601 views
Skip to first unread message

Aymeric Augustin

unread,
Oct 12, 2014, 2:31:56 PM10/12/14
to django-d...@googlegroups.com
Hello,

I just posted the first update on this project:
https://myks.org/en/multiple-template-engines-for-django/#2014-10-12

My work in progress on the DEP is available here:
https://myks.org/en/multiple-template-engines-for-django/dep/

Feedback is welcome, especially on sections I’ve described as “done” in the update.

Thanks,

--
Aymeric.

Fred Stluka

unread,
Oct 12, 2014, 8:19:49 PM10/12/14
to django-d...@googlegroups.com
Excellent!  Thanks for the update.  I donated to the IndieGoGo
campaign.

--Fred
Fred Stluka -- mailto:fr...@bristle.com -- http://bristle.com/~fred/
Bristle Software, Inc -- http://bristle.com -- Glad to be of service!
Open Source: Without walls and fences, we need no Windows or Gates.

Anssi Kääriäinen

unread,
Oct 17, 2014, 8:40:42 AM10/17/14
to django-d...@googlegroups.com
On Sun, 2014-10-12 at 20:31 +0200, Aymeric Augustin wrote:
> Feedback is welcome, especially on sections I've described as "done" in the update.

The FAQ section says that template context processors isn't going to be
supported for context processors.

The context processors return a dictionary to be added to the context,
so there is nothing template language specific in this definition.

What is the rationale of dropping context processors out of the
proposal? It seems supplying different template engines with different
data isn't going to work well for any project in which one wants to
replace DTL templates.

- Anssi

Aymeric Augustin

unread,
Oct 17, 2014, 10:47:34 AM10/17/14
to django-d...@googlegroups.com
Hi Anssi,

On 17 oct. 2014, at 14:49, Anssi Kääriäinen <anssi.ka...@thl.fi> wrote:

> The FAQ section says that template context processors isn't going to be
> supported for context processors.

Indeed, at this time, my theoretical position is not to enforce such an API
and leave it up to template engines.

But I may settle for a pragmatic position if this results in every template
engine copy-pasting 50 lines of code to provide that feature.

As shown by the `render` shortcut, APIs in this area must be pragmatic,
even if that requires some compromise with the general design.

> The context processors return a dictionary to be added to the context,
> so there is nothing template language specific in this definition.

It’s implemented in RequestContext which used to be called DjangoContext
until magic-removal (2006) and lives in django.template.context. That’s why
I considered it part of the Django template language itself.

> What is the rationale of dropping context processors out of the
> proposal? It seems supplying different template engines with different
> data isn't going to work well for any project in which one wants to
> replace DTL templates.

Yes, providing all templates with a common set of request-specific values
is a useful feature. It was on my todo list :-)

--
Aymeric.



Aymeric Augustin

unread,
Oct 18, 2014, 6:09:52 PM10/18/14
to django-d...@googlegroups.com
Hello,

Here’s the second update:
https://myks.org/en/multiple-template-engines-for-django/#2014-10-19

Best,

--
Aymeric.

Aymeric Augustin

unread,
Oct 26, 2014, 5:37:11 PM10/26/14
to django-d...@googlegroups.com
Hello,

I just published the third update:
https://myks.org/en/multiple-template-engines-for-django/#2014-10-26

--
Aymeric.

Aymeric Augustin

unread,
Nov 1, 2014, 6:30:27 PM11/1/14
to django-d...@googlegroups.com
Hello,

I’m happy to annonce that the DEP is ready for public review!

Direct link, HTML:
https://myks.org/en/multiple-template-engines-for-django/dep/

Direct link, ReStructured Text:
https://raw.githubusercontent.com/aaugustin/mtefd/master/multiple-template-engines.rst

(I’m not reproducing it here because I don’t think email is a very good medium for communicating 50kB of markup.)

I’ve written a bit more about what “ready” means:
https://myks.org/en/multiple-template-engines-for-django/#2014-11-01

Of course, your regularly scheduled update will also be available (in half an hour):
https://myks.org/en/multiple-template-engines-for-django/#2014-11-02

I’m looking forward to your feedback!

--
Aymeric.

Michael Manfre

unread,
Nov 1, 2014, 7:54:37 PM11/1/14
to django-d...@googlegroups.com
Overall the DEP looks really good.

It's currently assumed that BaseEngine.select_template() will scan the list in order and return the first one it can load, but it might make sense to explicitly state that in the DEP.

To avoid having 3rd party template engines suffering some of the same disparity that 3rd party database backends faced, what are your thoughts on having the jinga2 engine maintained outside of core? This would leave only the string template reference implementation and the DTL in the core.

Regards,
Michael Manfre

>>>
>>> --
>>> Aymeric.
>>>
>>
>

--
You received this message because you are subscribed to the Google Groups "Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
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/AF442429-4EFF-4C78-804F-F47ADF453245%40polytechnique.org.
For more options, visit https://groups.google.com/d/optout.

Aymeric Augustin

unread,
Nov 2, 2014, 2:42:36 AM11/2/14
to django-d...@googlegroups.com
> On 2 nov. 2014, at 00:53, Michael Manfre <mma...@gmail.com> wrote:
>
> Overall the DEP looks really good.

Thanks!

> It's currently assumed that BaseEngine.select_template() will scan the list in order and return the first one it can load, but it might make sense to explicitly state that in the DEP.

I’ve clarified that in the docstring.

> To avoid having 3rd party template engines suffering some of the same disparity that 3rd party database backends faced, what are your thoughts on having the jinga2 engine maintained outside of core? This would leave only the string template reference implementation and the DTL in the core.


String template don’t have a concept of “loading” a template; they only support “rendering”. I will have to implement a custom loading infrastructure. That doesn’t make it a very good reference implementation. I even considered scraping it for this reason. So I think we need at least another one in core.

I was planning to build and maintain a Mako backend externally so as to check how things looks like from the other side of the fence.

Hopefully the well-defined a public API will make the lives of maintainers of third-party template engines easier. Also templates are simpler than databases :-)

--
Aymeric.


Collin Anderson

unread,
Nov 2, 2014, 7:50:01 PM11/2/14
to django-d...@googlegroups.com
Hi Aymeric,

Thanks for all of your work on this. Am I too late to discuss the settings?

I don't see much advantage to the OPTIONS dict. It is consistent with DATABASES, and it separates the engine specific settings from the common settings. However, it doesn't seem like that helpful of a distinction to the user, especially considering there's only 3(?) non-OPTIONS settings. It seems like it only opens up the door to misconfiguration. Could we just pop-off the 3 common settings when configuring the template engine?

Thanks,
Collin


Carl Meyer

unread,
Nov 3, 2014, 1:48:09 PM11/3/14
to django-d...@googlegroups.com
Hi Aymeric,

Great work!

I'm afraid that my review comments are lengthy. Feel free to suggest
that I provide them in some other format (issues and/or PRs on
https://github.com/aaugustin/mtefd ?) if that would be more useful.

* In the rationale section, it may be worth mentioning the specific case
of template-driven form widgets, since this is a pathologically bad case
for DTL performance (e.g. when rendering select-boxes with hundreds of
choices) and (at least as far as I'm concerned) a strong motivator for a
faster built-in templating option.

* In the "selecting an engine" section, I think option 1, if the only
API, has an additional downside beyond just boilerplate: it places
control over engine selection at the rendering site, which may be
outside the control of the project integrator. I still think it's good
to provide option 1 as an option for tight low-level control in atypical
cases.

* I don't agree with the characterization of option 1 as "ugly" in the
description of option 2: it's not ugly, it's a perfectly clean and
sensible API. It's just low-level, less convenient, and doesn't offer
override hooks for project integrators. (I would say option 2 is
actually uglier than option 1, because it is conceptually incoherent
given that template engines are responsible for their own template
finding, loading, and parsing.)

* The description for option 4 implies that ordering of template engines
is only useful if their directories overlap. This is not the case. I
would see ordering as perhaps most useful in cases where a project wants
to selectively (or wholly) override some templates provided by a
third-party app with replacements using a different engine. In this
case, there would be no overlapping directories in the configuration,
just the same template name provided in two different engines' directories.

* In the current DTL configuration, the relative priority of
`TEMPLATE_DIRS` vs app directories can be controlled via ordering of the
`TEMPLATE_LOADERS` setting. In your proposed configuration scheme, how
can one control the relative priority of `DIRS` vs `APP_DIRS`? This can
be quite important for overriding templates provided by third-party
apps. If that's the primary/only use case, perhaps it's sufficient to
just have `DIRS` always take priority, since that's the more
explicitly-configured option? (I see that this is what your sample
`BaseEngine` implementation does - if that's your proposal, it should be
more explicit in the DEP.)

* Similarly, since it's left up to the user to configure other loading
mechanisms that an engine might offer (presumably via OPTIONS), that
raises the question of how a user could control the priority of those
alternative loading mechanisms vs `DIRS` and `APP_DIRS`. Perhaps the
best choice here is to punt that issue to the individual template engine
and its OPTIONS.

* I assume it is permitted to omit the `DIRS` and `APP_DIRS`
configuration keys (with default values of `[]` and `False`,
respectively) if a template engine is being configured to load templates
only from a non-filesystem source?

* Along a similar vein, I think it should be permissible (though not
encouraged) for a template engine to refuse to define an app-dirs
subdirectory name. In this case it would simply be an error to attempt
to configure that template engine with `APP_DIRS: True`.

* Is there any meaning to the top-level keys in the `TEMPLATES` setting?
None is mentioned; the only one I can think of would be as a string that
one could use in the option-1 API to explicitly select a specific
engine. I think the ability to configure template engine priority will
be important, and a dictionary is problematic for that. Importing
OrderedDict is ugly boilerplate. So I wonder if `TEMPLATES` should be a
list of dictionaries rather than a dictionary of dictionaries; perhaps
with a `NAME` key if we need a string identifier for each configured engine?

* Related to the above, I am glad to see that the proposed configuration
scheme would allow configuring more than one instance of the same
template engine. I don't have any use case for this off the top of my
head, but my instinct says it's a useful capability to maintain. (This
would imply that we shouldn't re-use the BACKEND string itself as an
identifier for a particular configured engine.)

* Re CSRF compatibility: by what convention does a template engine know
if a `request` has been provided? (This is clarified by the template
object interface code below, but is left unclear at the first mention of
CSRF compatibility).

* I'm not convinced that rejecting the "switch to Babel" option for
makemessages actually reduces the scope / difficulty / disruptiveness of
this DEP. I think improving makemessages to handle multiple template
engines will likely involve an undesirable level of reimplementing
things Babel already does well (whereas since Babel already has support
for DTL syntax, makemessages' hacky handling of DTL could be removed
with a switch to Babel). There is already precedent in Django for
required dependencies for subsystems which are not enabled by default
and do not block the initial getting-started flow. I think a more
flexible makemessages will likely be best (and simplest) implemented as
a wrapper to Babel, perhaps settings some configuration defaults
according to what is known about the Django project structure.

* Re Django backend: I think it should be an error to attempt to
configure the DTL backend with `APP_DIRS: True` and `OPTIONS['LOADERS']`
set. Allowing self-contradictory configurations to pass silently,
ignoring one aspect of the user's expressed desires, is bad.

* It's not mentioned explicitly, but I presume the DTL backend's
`render` method will take an ordinary dict (not a `Context` instance) as
its `context` argument, and will automatically use `RequestContext` (and
thus context processors) if the `request` argument is provided? This
seems like the best approach to me (though for backwards-compatibility
it will also need to accept a `Context` instance, and even perhaps pull
the request out of a `RequestContext` instance if provided, at least for
a deprecation period).

* That gets into the question of how the public API and implementation
of `django.shortcuts.render` and `render_to_response` will change. This
isn't fully outlined in the DEP; perhaps it should be, since for most
people it's the primary entry point for templates?

* I'm confused about how you plan to organize the Python namespaces for
Django's template support. I see use of both `django.template` and
`django.templates` in various code examples, but if there is a
consistency to the usage I'm missing it (and I don't think
differentiating modules by a single letter would be a good plan,
anyway). Ideally it seems to me that the DTL (currently in
`django.template` and must probably stay there for
backwards-compatibility) and the new engine-configuration system would
reside in totally separate namespaces; having the latter reside in a
submodule of the former seems logically backward. The issue is finding a
good name for the latter, since `django.template` would be the obvious
choice. Perhaps `django.templating`? Or maybe your apparent choice of
`django.template.backends` is the best option in practice, even if it
implies a relationship that is inverted from the reality
(`django.template` is one of the backends supported by
`django.template.backends`; `django.template.backends` is not a feature
of `django.template`).

* Re jinja2 backend's 'env' option: can we remove the option to have
that point directly to an instance, and require that it point to a
callable accepting the other options and returning an instance? I don't
see a benefit to this option that outweighs the additional complexity it
introduces. In the worst case, if someone has a module-level instance
already, it's a trivial one-liner (or two-liner if you don't like
lambda) to create a function returning that instance. I don't agree with
the assertion that `project_name.jinja2.env` will be the most convenient
solution in general, because it means you have to manually handle the
default values for `autoescape`, `loader`, `auto_reload`, and
`undefined` that Django would otherwise provide. This is demonstrated by
your example jinja2.py module, most of which is boilerplate which could
be eliminated by instead defining a function that takes the options from
settings, with defaults already handled.

* You mention `SimpleTemplateResponse` and `TemplateResponse` in
Appendix A and note that they aren't really features of DTL (which I
agree with), but you don't provide anywhere a migration plan for them. I
would like to see them usable with any template engine, which shouldn't
be too hard. It does raise the question of whether they should be moved
to a different location.

* Re FAQ "Is it possible to use Django template filters or tags with
other engines?" - I'm not sure I agree with the strong assertion that
this "certainly will" be implemented as a third-party module. As you
mention in the previous FAQ answer, in general it will be much less work
and a better implementation for providers of custom DTL filters/tags to
provide the core functionality via simple Python functions (which can
then be trivially added to the context for most non-DTL template
languages, including Jinja2), and the DTL integration as thin wrappers
around the core function.

Whew! Thanks again for all your work on this project, and for reading
through all my comments :-)

Carl

Aymeric Augustin

unread,
Nov 3, 2014, 5:27:13 PM11/3/14
to django-d...@googlegroups.com
Hi Collin,

It’s exactly the right time to discuss APIs :-)

After pondering your proposal, I'm still +0 on consistency with DATABASES and CACHES, but I'll make that change if other people agree with you. Does anyone else have an opinion on this?

Thanks,

-- 
Aymeric.



--
You received this message because you are subscribed to the Google Groups "Django developers (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.

Carl Meyer

unread,
Nov 3, 2014, 5:54:38 PM11/3/14
to django-d...@googlegroups.com
Hi Collin and Aymeric,

On 11/03/2014 03:26 PM, Aymeric Augustin wrote:
> Hi Collin,
>
> It’s exactly the right time to discuss APIs :-)
>
> After pondering your proposal, I'm still +0 on consistency with
> DATABASES and CACHES, but I'll make that change if other people agree
> with you. Does anyone else have an opinion on this?
>
> Thanks,
>
> --
> Aymeric.
>
>
>> On 3 nov. 2014, at 01:50, Collin Anderson <cmawe...@gmail.com
>> <mailto:cmawe...@gmail.com>> wrote:
>>
>> Hi Aymeric,
>>
>> Thanks for all of your work on this. Am I too late to discuss the
>> settings?
>>
>> I don't see much advantage to the OPTIONS dict. It is consistent with
>> DATABASES, and it separates the engine specific settings from the
>> common settings. However, it doesn't seem like that helpful of a
>> distinction to the user, especially considering there's only 3(?)
>> non-OPTIONS settings. It seems like it only opens up the door to
>> misconfiguration. Could we just pop-off the 3 common settings when
>> configuring the template engine?

I favor keeping OPTIONS. I don't think OPTIONS will be significantly
confusing to beginners (it may even provide a useful hedge between "the
basics" and "the advanced knobs").

Once you are doing anything beyond the basics, the distinction between a
setting that is handled specially by Django vs one that is just passed
as-is to the template backend is an important distinction to keep clear.

OPTIONS provides clear indication (without referencing the docs) which
settings you can expect to provide to any template backend with
equivalent effects, and which ones are engine-specific. I think losing
this clear distinction is likely to result in much more
mis-configuration frustration than OPTIONS will.

Carl

Marc Tamlyn

unread,
Nov 4, 2014, 7:09:46 AM11/4/14
to django-d...@googlegroups.com
A few thoughts:

I like OPTIONS, I think it's a good idea for the reasons Carl suggested.

It would be preferable to have the backend configuration outside of `django.template`. `django.templating` seems reasonable, but even `django.template_backends` might be appropriate as it only contains backends.

Assuming we go for the "subdirectory" based convention for app directories (option 4?) it would seem appropriate to make this configurable. In particular I can imagine a possibility where you may want multiple instances of the same backend with different configuration (e.g. different jinja extensions which conflict to support multiple pluggable apps). The loading problem is the only obvious flaw I can see here. It's a weird use case though.

I agree the DEP needs to specify more clearly what happens with `render` and friends. I also think there's potential merit to Option 1 (engine=) support on these APIs even with Option 4 - there may be times you need to force the use of a particular engine.

Marc

--
You received this message because you are subscribed to the Google Groups "Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.

Collin Anderson

unread,
Nov 4, 2014, 8:45:57 AM11/4/14
to django-d...@googlegroups.com
Hi All,


On Monday, November 3, 2014 5:54:38 PM UTC-5, Carl Meyer wrote:
I favor keeping OPTIONS. I don't think OPTIONS will be significantly
confusing to beginners (it may even provide a useful hedge between "the
basics" and "the advanced knobs").

Once you are doing anything beyond the basics, the distinction between a
setting that is handled specially by Django vs one that is just passed
as-is to the template backend is an important distinction to keep clear.
 That makes sense, though, is it just me or is CONTEXT_PROCESSORS a fairly frequently configured setting? My main use case is to enable the request context processor.

Collin

Preston Timmons

unread,
Nov 4, 2014, 2:58:03 PM11/4/14
to django-d...@googlegroups.com
Hi Aymeric,

With the new template update, do you foresee django.utils.setup_test_template_loader and django.utils.restore_template_loaders still working?

Those aren't officially public api's, but they're useful nonetheless. Perhaps the way to do it in the future would be with override_settings and a dict loader?

Preston

Aymeric Augustin

unread,
Nov 4, 2014, 3:39:02 PM11/4/14
to django-d...@googlegroups.com
Hi Preston,

2014-11-04 20:58 GMT+01:00 Preston Timmons <preston...@gmail.com>:
With the new template update, do you foresee django.utils.setup_test_template_loader and django.utils.restore_template_loaders still working?

This is a good question. To be honest, I had filed it under "implementation details I'll figure out when I get there" :-)

If I end up having to rewrite them, which is quite possible, expect a new API. I don't like changing and restoring state with a pair of functions. I prefer context managers / decorators for such use cases.

Since you find them useful, and even though they're private APIs, I'm making a note to document changes to these functions.

-- 
Aymeric.

Aymeric Augustin

unread,
Nov 4, 2014, 5:28:03 PM11/4/14
to django-d...@googlegroups.com
Hi Carl,

Thank you very much for the thorough review!

Most of your comments are in line with my thinking and only require
clarifications in the DEP. Tomorrow I'll proof-read and push what I've
written tonight.

I'm answering on a few items below. Everything else I agree with :-)

2014-11-03 19:47 GMT+01:00 Carl Meyer <ca...@oddbird.net>:

* The description for option 4 implies that ordering of template engines
is only useful if their directories overlap. This is not the case. I
would see ordering as perhaps most useful in cases where a project wants
to selectively (or wholly) override some templates provided by a
third-party app with replacements using a different engine. In this
case, there would be no overlapping directories in the configuration,
just the same template name provided in two different engines' directories.

In version you read, I didn't find that implication; my reasoning was:

1 - If different engines look for files in the same directory, and you aren't
    careful, one may attempt to render a file intended for another and bad
    things will happen.

2 - Within different directories, it will usually be easier to avoid conflicts, if
    only to make sure the developer can tell what template in rendered. In
    hindsight, this isn't good advice.

The setup you're proposing is valid. It's the kind of idea I was describing
as a fallback scheme ("try to find an override version, fall back to the app's
default templates") in the last paragraph. I've revised it to remove idea 2
and be neutral about such setups.

* In the current DTL configuration, the relative priority of
`TEMPLATE_DIRS` vs app directories can be controlled via ordering of the
`TEMPLATE_LOADERS` setting. In your proposed configuration scheme, how
can one control the relative priority of `DIRS` vs `APP_DIRS`? This can
be quite important for overriding templates provided by third-party
apps. If that's the primary/only use case, perhaps it's sufficient to
just have `DIRS` always take priority, since that's the more
explicitly-configured option? (I see that this is what your sample
`BaseEngine` implementation does - if that's your proposal, it should be
more explicit in the DEP.)

Yes, `DIRS` always takes priority. I don't see an use case for the opposite
behavior (and there's an escape hatch described a few paragraphs below).
I've made that explicit in the DEP.
 
* Similarly, since it's left up to the user to configure other loading
mechanisms that an engine might offer (presumably via OPTIONS), that
raises the question of how a user could control the priority of those
alternative loading mechanisms vs `DIRS` and `APP_DIRS`. Perhaps the
best choice here is to punt that issue to the individual template engine
and its OPTIONS.

Yes, that's my choice. I've also made that explicit.

* Along a similar vein, I think it should be permissible (though not
encouraged) for a template engine to refuse to define an app-dirs
subdirectory name. In this case it would simply be an error to attempt
to configure that template engine with `APP_DIRS: True`.

I've chosen to make it mandatory for consistency across engines and
because every engine should support loading templates from directories.

Your suggestion would be easy to implement, but to me it looks like it's
adding something that doesn't have a use case. Is there a good reason?
 
* Is there any meaning to the top-level keys in the `TEMPLATES` setting?
None is mentioned; the only one I can think of would be as a string that
one could use in the option-1 API to explicitly select a specific
engine.

Yes, that's the use case. I've mentioned it.
 
I think the ability to configure template engine priority will
be important, and a dictionary is problematic for that. Importing
OrderedDict is ugly boilerplate. So I wonder if `TEMPLATES` should be a
list of dictionaries rather than a dictionary of dictionaries; perhaps
with a `NAME` key if we need a string identifier for each configured engine?

I'm torn between consistency with DATABASES and CACHES on one side
and the ugliness of OrderedDict on the other side... I chose the former
because I value consistency a lot and because I discouraged relying on the
order (but that's no longer true...)

I find the idea of extracting a special key called "NAME" and using it as the
identifier rather confusing.

The datastructure is really an ordered mapping of engine identifier => engine
configuration. There's no syntax for that in Python, so... `import collections`.
 
* Related to the above, I am glad to see that the proposed configuration
scheme would allow configuring more than one instance of the same
template engine. I don't have any use case for this off the top of my
head, but my instinct says it's a useful capability to maintain. (This
would imply that we shouldn't re-use the BACKEND string itself as an
identifier for a particular configured engine.)

Yes, it feels like a sane property even without a use case.

You could use it to have APP_DIRS take precedence over DIRS.

* I'm not convinced that rejecting the "switch to Babel" option for
makemessages actually reduces the scope / difficulty / disruptiveness of
this DEP. I think improving makemessages to handle multiple template
engines will likely involve an undesirable level of reimplementing
things Babel already does well (whereas since Babel already has support
for DTL syntax, makemessages' hacky handling of DTL could be removed
with a switch to Babel). There is already precedent in Django for
required dependencies for subsystems which are not enabled by default
and do not block the initial getting-started flow. I think a more
flexible makemessages will likely be best (and simplest) implemented as
a wrapper to Babel, perhaps settings some configuration defaults
according to what is known about the Django project structure.

I don't think I have enough information at this point to make a decision nor
that a decision is absolutely required right now. I've changed the DEP to
keep this option under consideration.
 
* It's not mentioned explicitly, but I presume the DTL backend's
`render` method will take an ordinary dict (not a `Context` instance) as
its `context` argument, and will automatically use `RequestContext` (and
thus context processors) if the `request` argument is provided? This
seems like the best approach to me (though for backwards-compatibility
it will also need to accept a `Context` instance, and even perhaps pull
the request out of a `RequestContext` instance if provided, at least for
a deprecation period).

Yes.
 
* That gets into the question of how the public API and implementation
of `django.shortcuts.render` and `render_to_response` will change. This
isn't fully outlined in the DEP; perhaps it should be, since for most
people it's the primary entry point for templates?

They don't change — well, almost :-)

They get a new keyword argument, `engine`.

I think I'll have to deprecate the current_app keyword argument and make it
an attribute of the request instead. That's an implementation contingency for
which I'll implement a deprecation path.
 
* I'm confused about how you plan to organize the Python namespaces for
Django's template support. I see use of both `django.template` and
`django.templates` in various code examples, but if there is a
consistency to the usage I'm missing it (and I don't think
differentiating modules by a single letter would be a good plan,
anyway).

It's a typo. Read `django.template` everywhere.
 
Ideally it seems to me that the DTL (currently in
`django.template` and must probably stay there for
backwards-compatibility) and the new engine-configuration system would
reside in totally separate namespaces; having the latter reside in a
submodule of the former seems logically backward.

Indeed. For lack of a better solution, I plan to let them live in the same
namespace. That gives:

django.template.backends.* - built-in backends
django.template.utils - utilities for supporting backends
django.template.* - implementation of the DTL 

I shall rewrite the docstring of django.template to explain that.
 
The issue is finding a
good name for the latter, since `django.template` would be the obvious
choice. Perhaps `django.templating`? Or maybe your apparent choice of
`django.template.backends` is the best option in practice, even if it
implies a relationship that is inverted from the reality
(`django.template` is one of the backends supported by
`django.template.backends`; `django.template.backends` is not a feature
of `django.template`).

To me the alternative would be to move the implementation of the DTL to
e.g. django.template.engine. I judged that it would create gratuitous code
churn and I chose not do to it but I can if you think it's useful. 

* You mention `SimpleTemplateResponse` and `TemplateResponse` in
Appendix A and note that they aren't really features of DTL (which I
agree with), but you don't provide anywhere a migration plan for them. I
would like to see them usable with any template engine, which shouldn't
be too hard. It does raise the question of whether they should be moved
to a different location.

My answer is the same as for `render` and `render_to_response`. Besides
their private method `resolve_context` won't be needed any more since
`Template.render` will accept a plain dict.

Since template responses couple request handling and template rendering,
they belong to django.http, django.template, or django.shortcuts. I don't
believe the other places are enough of an improvement to warrant moving
them.
 
* Re FAQ "Is it possible to use Django template filters or tags with
other engines?" - I'm not sure I agree with the strong assertion that
this "certainly will" be implemented as a third-party module. As you
mention in the previous FAQ answer, in general it will be much less work
and a better implementation for providers of custom DTL filters/tags to
provide the core functionality via simple Python functions (which can
then be trivially added to the context for most non-DTL template
languages, including Jinja2), and the DTL integration as thin wrappers
around the core function.

I've changed the language but I'm still convinced that someone will do it :-)

-- 
Aymeric.

Aymeric Augustin

unread,
Nov 4, 2014, 5:30:27 PM11/4/14
to django-d...@googlegroups.com
2014-11-04 14:45 GMT+01:00 Collin Anderson <cmawe...@gmail.com>:
That makes sense, though, is it just me or is CONTEXT_PROCESSORS a fairly frequently configured setting? My main use case is to enable the request context processor.

In my opinion the request context processor should be enabled by default.

I suspect the only reason why it isn't is to avoid changing the default settings (django.conf.global_settings).

--
Aymeric.

Aymeric Augustin

unread,
Nov 4, 2014, 5:39:33 PM11/4/14
to django-d...@googlegroups.com
Hi Marc,

2014-11-04 13:09 GMT+01:00 Marc Tamlyn <marc....@gmail.com>:
It would be preferable to have the backend configuration outside of `django.template`. `django.templating` seems reasonable, but even `django.template_backends` might be appropriate as it only contains backends.

See my answer to Carl's email. 

Assuming we go for the "subdirectory" based convention for app directories (option 4?) it would seem appropriate to make this configurable. In particular I can imagine a possibility where you may want multiple instances of the same backend with different configuration (e.g. different jinja extensions which conflict to support multiple pluggable apps). The loading problem is the only obvious flaw I can see here. It's a weird use case though.

Configuring the subdirectory doesn't save you if two conflicting apps ship their templates in identically named subdirectories.

In that situation you could configure a backend that has the subdirectory containing the templates for a conflicting app in DIRS and another backend that deals with the other conflicting app. It's messy, but so is the use case :-)

I agree the DEP needs to specify more clearly what happens with `render` and friends.

Yes, I'll add a paragraph about shortcuts and another about template responses in the implementation section.
 
I also think there's potential merit to Option 1 (engine=) support on these APIs even with Option 4 - there may be times you need to force the use of a particular engine.

Yes, option 1 is included in my proposal.
 
--
Aymeric.

Carl Meyer

unread,
Nov 4, 2014, 6:02:40 PM11/4/14
to django-d...@googlegroups.com


On 11/04/2014 03:27 PM, Aymeric Augustin wrote:
>
> 2014-11-03 19:47 GMT+01:00 Carl Meyer <ca...@oddbird.net
> <mailto:ca...@oddbird.net>>:
>
> * The description for option 4 implies that ordering of template engines
> is only useful if their directories overlap. This is not the case. I
> would see ordering as perhaps most useful in cases where a project wants
> to selectively (or wholly) override some templates provided by a
> third-party app with replacements using a different engine. In this
> case, there would be no overlapping directories in the configuration,
> just the same template name provided in two different engines'
> directories.
>
>
> In version you read, I didn't find that implication; my reasoning was:
>
> 1 - If different engines look for files in the same directory, and you
> aren't
> careful, one may attempt to render a file intended for another and bad
> things will happen.
>
> 2 - Within different directories, it will usually be easier to avoid
> conflicts, if
> only to make sure the developer can tell what template in rendered. In
> hindsight, this isn't good advice.
>
> The setup you're proposing is valid. It's the kind of idea I was describing
> as a fallback scheme ("try to find an override version, fall back to the
> app's
> default templates") in the last paragraph. I've revised it to remove idea 2
> and be neutral about such setups.

Yes, you're right. On second reading, the implication I asserted isn't
actually there. I was really objecting to the phrase "the intent of this
design..." which it sounds like you will remove.

> * In the current DTL configuration, the relative priority of
> `TEMPLATE_DIRS` vs app directories can be controlled via ordering of the
> `TEMPLATE_LOADERS` setting. In your proposed configuration scheme, how
> can one control the relative priority of `DIRS` vs `APP_DIRS`? This can
> be quite important for overriding templates provided by third-party
> apps. If that's the primary/only use case, perhaps it's sufficient to
> just have `DIRS` always take priority, since that's the more
> explicitly-configured option? (I see that this is what your sample
> `BaseEngine` implementation does - if that's your proposal, it should be
> more explicit in the DEP.)
>
> Yes, `DIRS` always takes priority. I don't see an use case for the opposite
> behavior (and there's an escape hatch described a few paragraphs below).
> I've made that explicit in the DEP.

I can't think of a use case either; I think that's the right choice.

> * Along a similar vein, I think it should be permissible (though not
> encouraged) for a template engine to refuse to define an app-dirs
> subdirectory name. In this case it would simply be an error to attempt
> to configure that template engine with `APP_DIRS: True`.
>
> I've chosen to make it mandatory for consistency across engines and
> because every engine should support loading templates from directories.
>
> Your suggestion would be easy to implement, but to me it looks like it's
> adding something that doesn't have a use case. Is there a good reason?

I don't feel strongly. The "use case" (that's a strong term for it) is
this: I don't usually put templates in apps, only in a single
project-wide templates directory. I can imagine a scenario where I am
implementing a specialized project-specific template backend (for some
reason - let's hand-wave past this), and it would feel extraneous to be
forced to name an app sub-directory that I plan to never use.

Clearly, this isn't a strong case - I can easily just pick some string
and move on. My suggestion is really motivated by the general principle
that configuration which is not strictly required for a good reason
should be optional, and that I don't see the harm in allowing it. (I
actually would guess that a naive implementation would work precisely as
I outlined, and you'd have to go out of your way in the implementation
to "validate" that a template backend defines the app-dirs name even
when APP_DIRS is `False`.)

> * Is there any meaning to the top-level keys in the `TEMPLATES` setting?
> None is mentioned; the only one I can think of would be as a string that
> one could use in the option-1 API to explicitly select a specific
> engine.
>
>
> Yes, that's the use case. I've mentioned it.
>
>
> I think the ability to configure template engine priority will
> be important, and a dictionary is problematic for that. Importing
> OrderedDict is ugly boilerplate. So I wonder if `TEMPLATES` should be a
> list of dictionaries rather than a dictionary of dictionaries; perhaps
> with a `NAME` key if we need a string identifier for each configured
> engine?
>
>
> I'm torn between consistency with DATABASES and CACHES on one side
> and the ugliness of OrderedDict on the other side... I chose the former
> because I value consistency a lot and because I discouraged relying on the
> order (but that's no longer true...)
>
> I find the idea of extracting a special key called "NAME" and using it
> as the
> identifier rather confusing.
>
> The datastructure is really an ordered mapping of engine identifier =>
> engine
> configuration. There's no syntax for that in Python, so... `import
> collections`.

Yes, I see this reasoning. It's probably the best of bad alternatives :/
My main concern is that if anyone forgets to use OrderedDict, their
settings file will easily give the visual impression of a "priority"
that may or may not actually be correct.

I'm almost tempted to propose that `django.conf.BaseSettings` should
warn if `TEMPLATES` has length > 1 and is an unordered dict, but I won't
go that far. I do think the DEP should be updated to use OrderedDict in
all examples with more than one template engine configured, and the
default startproject settings file should also use OrderedDict.

> * Related to the above, I am glad to see that the proposed configuration
> scheme would allow configuring more than one instance of the same
> template engine. I don't have any use case for this off the top of my
> head, but my instinct says it's a useful capability to maintain. (This
> would imply that we shouldn't re-use the BACKEND string itself as an
> identifier for a particular configured engine.)
>
>
> Yes, it feels like a sane property even without a use case.
>
> You could use it to have APP_DIRS take precedence over DIRS.
>
> * I'm not convinced that rejecting the "switch to Babel" option for
> makemessages actually reduces the scope / difficulty / disruptiveness of
> this DEP. I think improving makemessages to handle multiple template
> engines will likely involve an undesirable level of reimplementing
> things Babel already does well (whereas since Babel already has support
> for DTL syntax, makemessages' hacky handling of DTL could be removed
> with a switch to Babel). There is already precedent in Django for
> required dependencies for subsystems which are not enabled by default
> and do not block the initial getting-started flow. I think a more
> flexible makemessages will likely be best (and simplest) implemented as
> a wrapper to Babel, perhaps settings some configuration defaults
> according to what is known about the Django project structure.
>
>
> I don't think I have enough information at this point to make a decision nor
> that a decision is absolutely required right now. I've changed the DEP to
> keep this option under consideration.

That's reasonable.

> * It's not mentioned explicitly, but I presume the DTL backend's
> `render` method will take an ordinary dict (not a `Context` instance) as
> its `context` argument, and will automatically use `RequestContext` (and
> thus context processors) if the `request` argument is provided? This
> seems like the best approach to me (though for backwards-compatibility
> it will also need to accept a `Context` instance, and even perhaps pull
> the request out of a `RequestContext` instance if provided, at least for
> a deprecation period).
>
>
> Yes.
>
>
> * That gets into the question of how the public API and implementation
> of `django.shortcuts.render` and `render_to_response` will change. This
> isn't fully outlined in the DEP; perhaps it should be, since for most
> people it's the primary entry point for templates?
>
>
> They don't change — well, almost :-)
>
> They get a new keyword argument, `engine`.
>
> I think I'll have to deprecate the current_app keyword argument and make it
> an attribute of the request instead. That's an implementation
> contingency for
> which I'll implement a deprecation path.

Right.

I think the `context_instance` and `dirs` arguments should also be
deprecated (both `render` and `render_to_response` have both, since they
pass along *args/**kwargs to `render_to_string`)?

And `render` should no longer wrap the given context dict in a
RequestContext, but just pass it along to the backend's `render` as a dict.

And both `render` and `render_to_response` can probably gain explicit
signatures, rather than *args/**kwargs?

> * I'm confused about how you plan to organize the Python namespaces for
> Django's template support. I see use of both `django.template` and
> `django.templates` in various code examples, but if there is a
> consistency to the usage I'm missing it (and I don't think
> differentiating modules by a single letter would be a good plan,
> anyway).
>
>
> It's a typo. Read `django.template` everywhere.
>
>
> Ideally it seems to me that the DTL (currently in
> `django.template` and must probably stay there for
> backwards-compatibility) and the new engine-configuration system would
> reside in totally separate namespaces; having the latter reside in a
> submodule of the former seems logically backward.
>
>
> Indeed. For lack of a better solution, I plan to let them live in the same
> namespace. That gives:
>
> django.template.backends.* - built-in backends
> django.template.utils - utilities for supporting backends
> django.template.* - implementation of the DTL
>
> I shall rewrite the docstring of django.template to explain that.

I think that's probably again the best of poor alternatives, since I
can't think of a new name for the backends system that isn't forced.

> The issue is finding a
> good name for the latter, since `django.template` would be the obvious
> choice. Perhaps `django.templating`? Or maybe your apparent choice of
> `django.template.backends` is the best option in practice, even if it
> implies a relationship that is inverted from the reality
> (`django.template` is one of the backends supported by
> `django.template.backends`; `django.template.backends` is not a feature
> of `django.template`).
>
>
> To me the alternative would be to move the implementation of the DTL to
> e.g. django.template.engine. I judged that it would create gratuitous code
> churn and I chose not do to it but I can if you think it's useful.

No, I agree that that option would be too much churn for too little value.

> * You mention `SimpleTemplateResponse` and `TemplateResponse` in
> Appendix A and note that they aren't really features of DTL (which I
> agree with), but you don't provide anywhere a migration plan for them. I
> would like to see them usable with any template engine, which shouldn't
> be too hard. It does raise the question of whether they should be moved
> to a different location.
>
>
> My answer is the same as for `render` and `render_to_response`. Besides
> their private method `resolve_context` won't be needed any more since
> `Template.render` will accept a plain dict.
>
> Since template responses couple request handling and template rendering,
> they belong to django.http, django.template, or django.shortcuts. I don't
> believe the other places are enough of an improvement to warrant moving
> them.

If the template-backends system is staying in `django.template`, and
we're accepting that `django.template` contains both the backends layer,
and the DTL backend, then it's fine for them to stay there too.

> * Re FAQ "Is it possible to use Django template filters or tags with
> other engines?" - I'm not sure I agree with the strong assertion that
> this "certainly will" be implemented as a third-party module. As you
> mention in the previous FAQ answer, in general it will be much less work
> and a better implementation for providers of custom DTL filters/tags to
> provide the core functionality via simple Python functions (which can
> then be trivially added to the context for most non-DTL template
> languages, including Jinja2), and the DTL integration as thin wrappers
> around the core function.
>
>
> I've changed the language but I'm still convinced that someone will do
> it :-)

Thanks for the response! Looking forward to seeing this in Django,

Carl

Collin Anderson

unread,
Nov 4, 2014, 9:21:17 PM11/4/14
to django-d...@googlegroups.com

On Tuesday, 4 November 2014 17:30:27 UTC-5, Aymeric Augustin wrote:
In my opinion the request context processor should be enabled by default.
+1 
I suspect the only reason why it isn't is to avoid changing the default settings (django.conf.global_settings).
Right. Can we uncomment it anyway? I can't imagine that there are many people are using the "request" name for anything other than the django request.

Or, I would also be happy with a render('template.html', {'request': request, 'myvar': 3}) convention and then stop using context processors completely.

Thanks,
Collin

Aymeric Augustin

unread,
Nov 5, 2014, 3:43:28 AM11/5/14
to django-d...@googlegroups.com
Hi Carl,

2014-11-05 0:02 GMT+01:00 Carl Meyer <ca...@oddbird.net>:

I can imagine a scenario where I am
implementing a specialized project-specific template backend (for some
reason - let's hand-wave past this), and it would feel extraneous to be
forced to name an app sub-directory that I plan to never use.

That makes sense. I've allowed templates engines not to provide the
basic loading features but in that case I've required them to raise an
exception if DIRS isn't empty or APP_DIRS isn't False.
 
I do think the DEP should be updated to use OrderedDict in
all examples with more than one template engine configured,

I've made this change in the only example that had two engines.
 
and the default startproject settings file should also use OrderedDict.

Well, the good news is that we don't need to put TEMPLATES
in the auto-generated settings file. The defaults just work if you're
putting templates in apps.

If we decided to add it for easier customisation, you're right, we
should include the OrderedDict, or it would be a Gun Pointed at
User's Feet, waiting for them to add a second engine.
 
I think the `context_instance` and `dirs` arguments should also be
deprecated (both `render` and `render_to_response` have both, since they
pass along *args/**kwargs to `render_to_string`)?

And `render` should no longer wrap the given context dict in a
RequestContext, but just pass it along to the backend's `render` as a dict.

And both `render` and `render_to_response` can probably gain explicit
signatures, rather than *args/**kwargs?

OK, I won't get away with hand-vawing :-)

I'll let you know when I have a specification ready for review.

--
Aymeric.

Aymeric Augustin

unread,
Nov 5, 2014, 3:48:26 AM11/5/14
to django-d...@googlegroups.com
Hi Collin,

2014-11-05 3:21 GMT+01:00 Collin Anderson <collinm...@gmail.com>:
On Tuesday, 4 November 2014 17:30:27 UTC-5, Aymeric Augustin wrote: 
I suspect the only reason why it isn't is to avoid changing the default settings (django.conf.global_settings).
Right. Can we uncomment it anyway?

The problem with changing global_settings is that we don't have any way to provide a deprecation path. However, since we have the checks framework, we've started making such changes and attempting to warn users with checks. Would you like to explore this direction?

I consider this idea to be independent from my refactoring.

Or, I would also be happy with a render('template.html', {'request': request, 'myvar': 3}) convention and then stop using context processors completely.

render(request, template_name, context) is such a strong convention at this point that I prefer keeping it.

Of course, I expect many template engines to simply push the request into the context and move on :-)

--
Aymeric.

Aymeric Augustin

unread,
Nov 5, 2014, 5:45:09 PM11/5/14
to django-d...@googlegroups.com
> On 5 nov. 2014, at 09:42, Aymeric Augustin <aymeric....@polytechnique.org> wrote:
>
> I'll let you know when I have a specification ready for review.


I just pushed an implementation plan for shortcuts and template responses.

Search for `render(request, template_name` in the DEP or look at the history in
https://github.com/aaugustin/mtefd/commits/master/multiple-template-engines.rst

--
Aymeric.

Tim Graham

unread,
Nov 5, 2014, 7:16:40 PM11/5/14
to django-d...@googlegroups.com
Hi Aymeric,

Nice work on the DEP. I tend to agree with Carl that I like a 'NAME' key in TEMPLATES rather than requiring the use of OrderedDict, but I can also see why you don't. I think it might simply the implementation if TEMPLATES was always a list of dictionaries rather than allowing it to be a dict or an OrderedDict. But if you decide not to go that route: if Django iterates over a plain dict to select a template, it seems that could result in some weird performance issues, e.g. if a page that expects template loader 'A' and sometimes tries 'A' as the first loader, sometimes as the second, etc (assuming there is some performance penalty for trying a loader and not finding the template). If it were me, I think I'd always enforce ordering if len(TEMPLATES) > 1 as Carl suggested. If the only downside is the ugliness of OrderedDict, well I think it might save some headaches and support queries.

Tim

Carl Meyer

unread,
Nov 5, 2014, 7:31:30 PM11/5/14
to django-d...@googlegroups.com
On 11/05/2014 05:16 PM, Tim Graham wrote:
> Nice work on the DEP. I tend to agree with Carl that I like a 'NAME' key
> in TEMPLATES rather than requiring the use of OrderedDict, but I can
> also see why you don't. I think it might simply the implementation if
> TEMPLATES was always a list of dictionaries rather than allowing it to
> be a dict or an OrderedDict. But if you decide not to go that route: if
> Django iterates over a plain dict to select a template, it seems that
> could result in some weird performance issues, e.g. if a page that
> expects template loader 'A' and sometimes tries 'A' as the first loader,
> sometimes as the second, etc (assuming there is some performance penalty
> for trying a loader and not finding the template). If it were me, I
> think I'd always enforce ordering if len(TEMPLATES) > 1 as Carl
> suggested. If the only downside is the ugliness of OrderedDict, well I
> think it might save some headaches and support queries.

Yes, I'm still a bit uneasy with the idea of even allowing a
multi-engine `TEMPLATES` to be an unordered dict as well. I hadn't
thought about the fact that it is relevant for performance reasons even
if you aren't doing any template overrides. It just seems like a bad
idea to allow it at all.

And like Tim, I do feel that a `NAME` key would also still be a
reasonable alternative, even though it breaks the parallel with
`DATABASES` and `CACHES` (there is not really a parallel anyway, since
those are unordered mappings, which is a different data structure).

On the other hand, I do recognize that the name is by nature a referent
(and should be unique), and thus having it be the key in a mapping makes
a lot of sense.

Seeing the `OrderedDict` syntax in the example in the latest PEP update
made me sad. So much more verbose than dictionary syntax; I think people
will really be tempted to skip it if we don't force ordered-ness, but I
think unordered will cause them even more problems.

Sure wish Python had builtin syntax for ordered mappings :/

Carl

Collin Anderson

unread,
Nov 5, 2014, 7:57:49 PM11/5/14
to django-d...@googlegroups.com
Could we do a list of 2-tuples instead of OrderdDict?

Aymeric Augustin

unread,
Nov 6, 2014, 3:14:54 PM11/6/14
to django-d...@googlegroups.com
> On 6 nov. 2014, at 01:31, Carl Meyer <ca...@oddbird.net> wrote:
>
> Seeing the `OrderedDict` syntax in the example in the latest PEP update
> made me sad.

I’m convinced.

I had an interesting idea for NAME. It can default to the name of the engine.
Then only people who configure more than one instance of a given engine
need to configure it. I updated the DEP accordingly. TEMPLATES becomes
quite elegant.

This “smart” idea that turns out to be stupid for an obvious reason. Let me
know if I missed something.

--
Aymeric.

Carl Meyer

unread,
Nov 6, 2014, 4:32:49 PM11/6/14
to django-d...@googlegroups.com
Looks great to me, as long as the error message for non-unique `NAME` is
clear about what needs to be done. Much easier to read and write the
`TEMPLATES` setting now.

Carl

Preston Timmons

unread,
Nov 7, 2014, 12:51:30 PM11/7/14
to django-d...@googlegroups.com
Aymeric,

Great work on this. I have a few more questions:

First, if multiple engines are configured, how do you see the error being displayed if a template isn't found in any of them? Currently, this originates from the template loaders. For instance, the filesystem loader raises a TemplateDoesNotExist with a list of templates it tried.

Second, if I want to get a template from within a script, do I have to manually loop through the engines? Or is there a higher-level get_template that encapsulates this?

Third, if I understand right, extending templates would only happen within the template engine that found the template. That means if multiple Django template engines were specified, the extends tag would not extend templates from other Django engines, even when specified. Is this correct?

Preston

Aymeric Augustin

unread,
Nov 7, 2014, 3:25:45 PM11/7/14
to django-d...@googlegroups.com
Hi Preston,

On 7 nov. 2014, at 18:51, Preston Timmons <preston...@gmail.com> wrote:

> First, if multiple engines are configured, how do you see the error being displayed if a template isn't found in any of them? Currently, this originates from the template loaders. For instance, the filesystem loader raises a TemplateDoesNotExist with a list of templates it tried.

Django will still raise the same TemplateDoesNotExist exception. I think I’ll build an error message by concatenating exceptions raised by each engine.

> Second, if I want to get a template from within a script, do I have to manually loop through the engines? Or is there a higher-level get_template that encapsulates this?

I will preserve public APIs, including:

django.template.loader.get_template(template_name[, dirs])
django.template.loader.select_template(template_name_list[, dirs])

> Third, if I understand right, extending templates would only happen within the template engine that found the template. That means if multiple Django template engines were specified, the extends tag would not extend templates from other Django engines, even when specified. Is this correct?

Yes, that’s correct.

--
Aymeric.

Aymeric Augustin

unread,
Nov 9, 2014, 4:05:34 PM11/9/14
to django-d...@googlegroups.com
Hello,

Here’s my fifth update:
https://myks.org/en/multiple-template-engines-for-django/#2014-11-09

The first step of my project, as outlined in my original proposal, is complete.

--
Aymeric.

Aymeric Augustin

unread,
Nov 16, 2014, 3:17:04 AM11/16/14
to django-d...@googlegroups.com
On 4 nov. 2014, at 21:38, Aymeric Augustin <aymeric....@polytechnique.org> wrote:

2014-11-04 20:58 GMT+01:00 Preston Timmons <preston...@gmail.com>:
With the new template update, do you foresee django.utils.setup_test_template_loader and django.utils.restore_template_loaders still working?

If I end up having to rewrite them, which is quite possible, expect a new API. I don't like changing and restoring state with a pair of functions. I prefer context managers / decorators for such use cases.

Not only did that happen already 4dc4d12e27e4e0337568651136eee5b6f2171204, but I’m about to remove the replacement introduced in that commit in 151a01a581bc17afe4f6b2278b567730da01dcf9.

I’m proposing to use @override_settings(TEMPLATE_LOADERS=[…]) instead which looks much more explicit and straightforward to me.

-- 
Aymeric.


Aymeric Augustin

unread,
Nov 16, 2014, 3:19:38 AM11/16/14
to django-d...@googlegroups.com
Hello,

Here’s my sixth update:
https://myks.org/en/multiple-template-engines-for-django/#2014-11-16

I have a first pull request ready for review:
https://github.com/django/django/pull/3555

Whenever possible, I’ll merge changes that make sense regardless of the Multiple Template Engines Project in small batches, in order to minimize the size of the final pull request.

--
Aymeric.

Aymeric Augustin

unread,
Nov 22, 2014, 6:05:17 PM11/22/14
to django-d...@googlegroups.com
Hello,

I published my seventh update:
https://myks.org/en/multiple-template-engines-for-django/#2014-11-23

I have another pull request ready for review:
https://github.com/django/django/pull/3605

Let me know if you have any questions!

--
Aymeric.

Aymeric Augustin

unread,
Nov 30, 2014, 4:37:31 AM11/30/14
to django-d...@googlegroups.com
Hello,

Here’s my eight update — this is getting repetitive :-)
https://myks.org/en/multiple-template-engines-for-django/#2014-11-30

--
Aymeric.

Luke Plant

unread,
Dec 1, 2014, 1:59:40 AM12/1/14
to django-d...@googlegroups.com
Hi Aymeric,

Just some quick feedback - I think it's perfectly reasonable not to be
writing any docs or tests at this point. It seems like the nitty-gritty
details are likely to be affecting various API decisions that you have
to make, and there is no point writing either docs or tests when API is
in flux. Some of your work - the default path - is going to be well
tested by virtue of Django's existing test suite.

Luke

On 30/11/14 09:37, Aymeric Augustin wrote:
> Hello,
>
> Here’s my eight update — this is getting repetitive :-)
> https://myks.org/en/multiple-template-engines-for-django/#2014-11-30
>


--
"Whom have I in heaven but You?
And there is none upon earth that I desire besides You." Psalm 73:25

Luke Plant || http://lukeplant.me.uk/

Aymeric Augustin

unread,
Dec 20, 2014, 5:57:36 PM12/20/14
to django-d...@googlegroups.com
Hello,

I haven’t written to this mailing-list for three weeks because nothing warranted your immediate attention.

Now the code is in reasonably good shape. Feel free to have a look:
https://github.com/aaugustin/django/commits/multiple-template-engines

I plan to merge this branch within a few days.

Updates for weeks 9 to 11 are available at the usual location:
https://github.com/aaugustin/django/commits/multiple-template-engines

--
Aymeric.

Aymeric Augustin

unread,
Dec 27, 2014, 5:59:37 PM12/27/14
to django-d...@googlegroups.com
Hello,

My twelfth update is online:
https://myks.org/en/multiple-template-engines-for-django/#2014-12-28

It comes with a question — should I drop `select_template` from the backend API? I think I should. Follow the link above for details.

Looking forward to your feedback,

--
Aymeric.

Tim Graham

unread,
Dec 27, 2014, 8:13:11 PM12/27/14
to django-d...@googlegroups.com
I agree with your expected behavior for select_template() and the conclusions you drew.

Preston Timmons

unread,
Dec 27, 2014, 10:10:53 PM12/27/14
to django-d...@googlegroups.com
I agree about the select_template() change as well.

Michael Manfre

unread,
Dec 28, 2014, 1:13:37 AM12/28/14
to django-d...@googlegroups.com
If I'm understanding your post correctly, any potential performance improvement that a special cased select_template would have would likely be negated by caching. Have you observed, or do you expect to see any significant performance hits to the test suite, which doesn't cache as intensely as live sites?

Regards,
Michael Manfre

On Sat, Dec 27, 2014 at 5:59 PM, Aymeric Augustin <aymeric....@polytechnique.org> wrote:
Hello,

Aymeric Augustin

unread,
Dec 28, 2014, 3:54:11 AM12/28/14
to django-d...@googlegroups.com
Hi Michael,

> On 28 déc. 2014, at 07:12, Michael Manfre <mma...@gmail.com> wrote:
>
> If I'm understanding your post correctly, any potential performance improvement that a special cased select_template would have would likely be negated by caching.

Sorry, I didn’t explain sufficiently clearly. My reasoning was:

1) Is there any situation where I can call a backend's select_template? Yes, when only one template engine is configured.
2) Does this have any advantages? Unclear, it may allow some performance optimizations at the backend level but that's completely theoretical.
3) Does that make it worth keeping select_template? Probably not.

> Have you observed, or do you expect to see any significant performance hits to the test suite, which doesn't cache as intensely as live sites?

No, I don’t expect to see a measurable impact on the test suite’s run time, because the current code and the new code will do roughly the same amont of work and neither optimizes anything.

--
Aymeric.

Michael Manfre

unread,
Dec 28, 2014, 10:30:19 AM12/28/14
to django-d...@googlegroups.com
Thanks for the explanation. It makes sense to remove select_template.

Regards,
Michael Manfre


--
Aymeric.

--
You received this message because you are subscribed to the Google Groups "Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
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/05BAC9A8-41C3-4FD8-88F2-531E933C517C%40polytechnique.org.
For more options, visit https://groups.google.com/d/optout.

Aymeric Augustin

unread,
Jan 3, 2015, 6:23:37 PM1/3/15
to django-d...@googlegroups.com
Hello,

Here’s the thirteenth update (good thing I learnt all these ordinals when I was a kid!)
https://myks.org/fr/multiple-template-engines-for-django/#2015-01-04

At this point my main concern is the 1.8 feature freeze scheduled in one week.
Dealing properly with some of the items I listed in my report for week 11 may
require changes falling in the "new features” bucket and therefore being
postponed to Django 1.9. At worst, I’ll have to document that some features
only work with the Django template language in Django 1.8. That’s sad but not
worth delaying the entire project until early 2016.

--
Aymeric.

Jeremy Dunck

unread,
Jan 3, 2015, 8:44:52 PM1/3/15
to django-d...@googlegroups.com
If getting proper support for other template backends would only delay the 1.8 release timeline by a couple weeks, I think that is preferable to a generalized 1.8 backend which only include DTL until 1.9.

What do others think?


>>>>>>>>>>
>>>>>>>>>> --
>>>>>>>>>> Aymeric.
>>>>>>>>>>
>>>>>>>>>
>>>>>>>>
>>>>>>>
>>>>>>
>>>>>
>>>>
>>>
>>
>

--
You received this message because you are subscribed to the Google Groups "Django developers  (Contributions to Django itself)" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-develop...@googlegroups.com.
To post to this group, send email to django-d...@googlegroups.com.
Visit this group at http://groups.google.com/group/django-developers.

Michael Manfre

unread,
Jan 3, 2015, 9:11:13 PM1/3/15
to django-d...@googlegroups.com
+1 to delaying the freeze to get this feature fully in place, especially since 1.8 will be an LTS release. Is there precedent to doing a freeze with an exemption for an in progress feature? If so, that is another option to an outright extension.

Regards,
Michael Manfre

Florian Apolloner

unread,
Jan 4, 2015, 3:51:22 AM1/4/15
to django-d...@googlegroups.com
On Sunday, January 4, 2015 2:44:52 AM UTC+1, jdunck wrote:
If getting proper support for other template backends would only delay the 1.8 release timeline by a couple weeks, I think that is preferable to a generalized 1.8 backend which only include DTL until 1.9.

Define proper support. Either way -1 on pushing the alpha further.

Tim Graham

unread,
Jan 4, 2015, 4:09:02 PM1/4/15
to django-d...@googlegroups.com
I don't think it's fair to put pressure on Aymeric like that. It seems to me with should, if anything, be more conservative with an LTS -- not try to cram in last minute features. We have 2-3 months until the scheduled final release -- if we liberalize our "rules", I'm sure we can kick that date out the window. My own hope (from what others have expressed interest in) is to move Django to a more rapid release cycle of 6-9 months instead of the more historical 9-12 months. I believe this feature will be all the better in 1.9 after getting a first version out the door in 1.8.

Aymeric Augustin

unread,
Jan 4, 2015, 4:47:02 PM1/4/15
to django-d...@googlegroups.com
On 4 janv. 2015, at 22:09, Tim Graham <timog...@gmail.com> wrote:

I don't think it's fair to put pressure on Aymeric like that.

My throughput on this project has been rather stable. There’s only so much I
can do by next week. Pressure won’t add hours to my days anyway ;-) As a
consequence I don’t want to weigh in one way or another. I’ll just do my best
within the allotted time.

As Tim reminded us, 1.8 will be a LTS, which means that robustness is more
important than features. I’m working under this assumption and erring on the
side of caution when introducing new APIs.


Here are the main limitations I know of, to help make the decision.

Missing pieces

Documentation: I’m making good progress and I’m confident that it will be
committed within one week.

Deprecating Template.render(Context) - where Template is a backend-specific
Template, not a django.template.Template: I think I can complete the patch
next weekend.

i18n / makemessages: I hope I can get away with a small hack to support both
the DTL and Jinja2, as suggested in #23299 [1]. I haven’t checked the code [2].
Limitation: makemessages won’t work with third-party template backends.
Timeline: probably 1.9 — one suggested solution is to integrate Babel.

Origin API: I have left aside the discussion with Preston Timmons for now. It's
hard to estimate what its outcome will be and how much work it will require.
Limitation: the debug view may be less useful with non-DTL engines when a
template isn’t found.
Timeline: unknown

Traceback integration: perhaps Jinja2’s traceback integration will just work and
peacefully cohabit with Django’s custom implementation but I’m not taking bets.
Limitation: the debug view may be less useful with non-DTL engines when
rendering a template raises an exception.
Timeline: unknown

django.contrib.admindocs & syndication: they depend on Engine.get_current().
Limitation: these apps won't work when zero or more than one DjangoTemplates
engines are configured.
Timeline: hopefully 1.8 beta


Broken pieces

current_app: currently it’s impossible to reverse namespaced URLs with a non-
default instance namespace outside of a request handling cycle [3] e.g. when
sending email. Today’s discussion with Florian on #django-dev shows that this
regression may be a problem.

Plus, of course, everything that will be reported after the alpha release :-)


I believe everything else is sufficiently small not to qualify as a new feature,
meaning that it can be taken care of after the alpha and before the beta.

Making sure that all Django-specific template tags have plain Python
equivalents may require documenting new APIs but they will be transliterations
of existing APIs so there’s very little at stake.

Reviewing and perhaps updating the list of context processors in the default
settings.py template seems small enough to be changed in the beta.

Fixing the debug view that still depends on Engine.get_default() counts as a
bugfix, not a new feature.


-- 
Aymeric.

Aymeric Augustin

unread,
Jan 10, 2015, 6:03:20 PM1/10/15
to django-d...@googlegroups.com
Hello,

Here’s episode 14:
https://myks.org/en/multiple-template-engines-for-django/#2015-01-11

Hopefully I’ll reach the point where I don’t have enough material to write
a weekly update by the end of February :-)

--
Aymeric.

Aymeric Augustin

unread,
Jan 18, 2015, 4:49:17 PM1/18/15
to django-d...@googlegroups.com
Hello,

I published my update for week 15:
https://myks.org/en/multiple-template-engines-for-django/#2015-01-18

--
Aymeric.

Aymeric Augustin

unread,
Jan 25, 2015, 5:29:50 PM1/25/15
to django-d...@googlegroups.com
Hello,

Here’s the final weekly update for this project:
https://myks.org/en/multiple-template-engines-for-django/#2015-01-25

Huge thanks for everyone who helped me along the way!

--
Aymeric.

aRkadeFR

unread,
Jan 29, 2015, 8:29:52 AM1/29/15