Root Cause: The `get_templatetag_libraries` method in
`django.template.backends.django.DjangoTemplates` calls the
`get_installed_libraries` method. The `get_installed_libraries` method
calls `apps.get_app_configs` which raises a `AppRegistryNotReady` error if
used in standalone mode.
Adding a try except around `get_installed_libraries` is a quick fix that
worked for me.
{{{#!python
def get_templatetag_libraries(self, custom_libraries):
"""
Return a collation of template tag libraries from installed
applications and the supplied custom_libraries argument.
"""
try:
libraries = get_installed_libraries()
except AppRegistryNotReady:
libraries = {}
libraries.update(custom_libraries)
return libraries
}}}
Can you advise if this is a reasonable solution? If so, I can submit a PR.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
* needs_better_patch: => 0
* type: Uncategorized => Bug
* needs_tests: => 0
* needs_docs: => 0
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:1>
Comment (by timgraham):
I'm just browsing the code so I'm not certain, but it looks like that
solution wouldn't make any of the built-in template tags and filters
available.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:2>
Comment (by AlJohri):
Replying to [comment:2 timgraham]:
> I'm just browsing the code so I'm not certain, but it looks like that
solution wouldn't make any of the built-in template tags and filters
available.
I'm able to use the `safe` built-in in my project with this patch applied
so I think built-ins are still available?
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:3>
* status: new => closed
* resolution: => invalid
* component: Uncategorized => Template system
Comment:
Yes, built-ins isn't the correct term. I think you won't be able to load
anything from `django.templatetags` (cache, i18n, etc.)
Anyway, I think you're hitting that exception because you're missing a
[https://docs.djangoproject.com/en/stable/topics/settings/#calling-django-
setup-is-required-for-standalone-django-usage django.setup()] call that's
required for standalone usage.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:4>
Comment (by AlJohri):
Replying to [comment:4 timgraham]:
> Yes, built-ins isn't the correct term. I think you won't be able to load
anything from `django.templatetags` (cache, i18n, etc.)
>
> Anyway, I think you're hitting that exception because you're missing a
[https://docs.djangoproject.com/en/stable/topics/settings/#calling-django-
setup-is-required-for-standalone-django-usage django.setup()] call that's
required for standalone usage.
Ah, thank you!
Might want to add a note to the documentation similar to this in v1.7:
https://docs.djangoproject.com/en/1.7/ref/templates/api/#configuring-the-
template-system-in-standalone-mode
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:5>
Comment (by timgraham):
We don't update the docs for old, unsupported versions. If there's a spot
in the stable version docs to update, feel free to send a PR. Thanks.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:6>
* stage: Unreviewed => Accepted
Comment:
Actually it would be nice -- if it's possible -- for the template engine
to be usable, albeit with limited functionality, outside of a Django
project, more precisely without having to configure global Django
settings.
The cache, i18n, etc. features wouldn't work because they need
configuration provided by Django settings. That's an expected limitation
of this feature and it could be documented.
The biggest problem I can see is that we have no good way to test this,
this Django's tests run with configured settings.
Optimistically accepting this requirement, because I think it's a sane
design principle, but without guarantees that it can be met.
This ticket is mostly a matter of figuring out and documenting what can
work and what can't work without settings.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:7>
* status: closed => new
* type: Bug => Cleanup/optimization
* version: 1.10 => master
* resolution: invalid =>
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:8>
Comment (by Quentin Fulsher):
Hey all, I'd like to do some work on this and get more familiar with
Django's template system. After reading over the thread it sounds like the
first step would be to develop some tests to determine which tags need
settings configured and which don't. I figure after we have a module of
tests running without settings we can figure out how to integrate that
into the existing django testing framework.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:9>
Comment (by reficul31):
For testing the code, is it possible to add a method to @override.settings
that removes all the settings so that the test case can run without them?
Or another solution can be to individually override each setting used by
the template tag and set it to NULL and test. Eg. The time filter uses
settings.TIME_FORMAT to get the time in the required format. It might be
possible to set @setting.override(TIME_FORMAT=NULL) or something similar.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:10>
* status: new => assigned
* owner: nobody => reficul31
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:11>
* needs_better_patch: 0 => 1
* has_patch: 0 => 1
* needs_tests: 0 => 1
Comment:
[https://github.com/django/django/pull/7965 PR]
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:12>
Comment (by Aymeric Augustin):
In fact using `django.template.Engine` in standalone mode already works:
{{{
>>> from django.template import Context, Engine
>>> engine = Engine()
>>> template = engine.from_string("Hello {{ name }}!")
>>> context = Context({'name': "world"})
>>> template.render(context)
'Hello world!'
}}}
`DjangoTemplates` is a thin integration layer for configuring an `Engine`
according to the project settings. It doesn't make sense to remove its
dependencies on settings. Just use `Engine` directly.
The documentation explains the roles of these classes without ambiguity
and specifically mentions using the template engine outside of a Django
project (meaning without Django settings):
https://docs.djangoproject.com/en/1.10/topics/templates/#engine
> django.template.Engine encapsulates an instance of the Django template
system. The main reason for instantiating an Engine directly is to use the
Django template language outside of a Django project.
> django.template.backends.django.DjangoTemplates is a thin wrapper
adapting django.template.Engine to Django’s template backend API.
For these reasons, I don't see what needs to be done here.
https://docs.djangoproject.com/en/1.10/topics/templates/#components
`DjangoTemplates`
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:13>
Comment (by reficul31):
Replying to Aymeric:
I read over the docs of the django.template.engine and knew that it worked
in standalone mode. I thought the gist of the ticket was to provide
DjangoTemplates with that functionality too. I might be wrong but is it a
functionality that could cause problems? Eg. For most of my projects I use
DjangoTemplates backend and it would be nice if i could test my templates
on it.
Again I might be completely wrong.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:14>
* status: assigned => closed
* resolution: => wontfix
Comment:
Perhaps this analogy will help:
django.template.Engine ~ sqlite3.connect
django.template.backends.django.DjangoTemplates ~
django.db.backends.sqlite3.base.DatabaseWrapper
The two live in the same namespace for historical reasons. Moving the
implementation of the engine outside of `django.template` would be
backwards incompatible for no significant benefit.
I wrote a
[https://github.com/django/django/blob/master/django/template/__init__.py
large docstring] to clarify which modules belong to the standalone
template engine and which modules allow using arbitrary backends with a
unified API. See also DEP 182.
----
Replying to [comment:14 reficul31]:
> I read over the docs of the django.template.engine and knew that it
worked in standalone mode.
If you think the docs could state more clearly that this is the API to use
if you want to use the Django template engine in standalone mode, let's
improve them.
(Since it's hard to figure out how docs that you wrote yourself could be
unclear to others, I'm not in the best position to do that.)
> I thought the gist of the ticket was to provide DjangoTemplates with
that functionality too.
Unfortunately, it was incorrectly accepted based on a misunderstanding. It
should have been closed as wontfix. I realized the problem only when I saw
your PR.
> I might be wrong but is it a functionality that could cause problems?
Yes, it would worsen the problem that the existence of this ticket
demonstrates.
Even though the documentation is unambiguous, there's already some
confusion between the concepts of "template engine" (any library that can
render templates) and "template backend" (a thin integration layer for
configuring a template engine from Django settings). Adding to the
ambiguity by blurring the roles of Engine and DjangoTemplates would
increase confusion.
> Eg. For most of my projects I use DjangoTemplates backend and it would
be nice if i could test my templates on it.
DjangoTemplates is nothing more than an Engine configured from Django
settings. Here's the whole implementation:
{{{
def __init__(self, params):
params = params.copy()
options = params.pop('OPTIONS').copy()
options.setdefault('autoescape', True)
options.setdefault('debug', settings.DEBUG)
options.setdefault('file_charset', settings.FILE_CHARSET)
libraries = options.get('libraries', {})
options['libraries'] = self.get_templatetag_libraries(libraries)
super().__init__(params)
self.engine = Engine(self.dirs, self.app_dirs, **options)
}}}
and then there's a couple methods that forward to the corresponding
methods on Engine.
If your projet uses Django settings and the DjangoTemplates backend, then
your tests should use Django settings as well, and there's no use making
DjangoTemplates work without settings.
If your projet doesn't use Django settings and configures an Engine in
standalone mode, then you don't use DjangoTemplates, not does it make any
sense, since you don't have Django settings.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:15>
Comment (by reficul31):
Thank you Aymeric for taking out the time and explaining the issue. I get
the concept now. I guess an upgrade to the docs might help the other users
see the it more clearly too.
--
Ticket URL: <https://code.djangoproject.com/ticket/27130#comment:16>