Hi,
We're trying to create a template from string using DjangoTemplates.from_string() of the default template backend, which wraps the result of Engine.from_string() to construct an instance of the Template class defined in the backend definition file: django/template/backends/django.py#30
This Template class differs from the Engine-delivered Template in that it accepts a dictionary as the context, see
https://docs.djangoproject.com/en/4.0/topics/templates/#django.template.backends.base.Template.render.
The default backend's engine is easily retrieved via django.template.Engine.get_default(). This function identifies the first configured DjangoTemplates backend, and then returns its .engine attribute. As a result, when from_string() is called, it will be called on the engine and not on the backend, thus the wrapping Template() call is missing.
I would like to propose adding a get_default_backend() function to django.template.Engine, which is like get_default(), but returns the backend itself (and not its .engine attribute). get_default() can then be adjusted to simply return get_default_backend().engine.
While trying to solve the issue (context argument type mismatch: dict vs Context), I found the docs not very helpful, as they are not very accurate in the distinction between a backend and its engine. I've also added a commit that clarifies that language.
I have submitted a patch here:
https://github.com/django/django/pull/15944
FWIW, the problem can also be solved on the application layer, like:
def get_default_template_backend():
# Ad-hoc implementation of
https://github.com/django/django/pull/15944
from django.template import engines
for backend in engines.all():
if isinstance(backend, DjangoTemplates):
return backend
raise ImproperlyConfigured("No DjangoTemplates backend is configured.")
However and IMHO, this needlessly duplicates the logic from get_default() and adds undue complication to the app (like having to know about and looping over the .all() iterable; raising the exception), whereas that complexity already is in the core.
Please let me know what you think!
Thanks,
Peter
--
https://desec.io/