#27130 closed Cleanup/optimization (wontfix)
Allow using the DjangoTemplates engine without configuring settings
Reported by: | Al Johri | Owned by: | reficul31 |
---|---|---|---|
Component: | Template system | Version: | dev |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Accepted | |
Has patch: | yes | Needs documentation: | no |
Needs tests: | yes | Patch needs improvement: | yes |
Easy pickings: | no | UI/UX: | no |
Description
Using Django Templates in standalone mode raises a AppRegistryNotReady
error.
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.
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.
Change History (16)
comment:1 by , 8 years ago
Type: | Uncategorized → Bug |
---|
follow-up: 3 comment:2 by , 8 years ago
comment:3 by , 8 years ago
Replying to 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?
follow-up: 5 comment:4 by , 8 years ago
Component: | Uncategorized → Template system |
---|---|
Resolution: | → invalid |
Status: | new → closed |
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 django.setup() call that's required for standalone usage.
comment:5 by , 8 years ago
Replying to 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 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
comment:6 by , 8 years ago
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.
comment:7 by , 8 years ago
Triage Stage: | Unreviewed → Accepted |
---|
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.
comment:8 by , 8 years ago
Resolution: | invalid |
---|---|
Status: | closed → new |
Summary: | Cannot use Django Templates in Standalone Mode → Allow using the DjangoTemplates engine without configuring settings |
Type: | Bug → Cleanup/optimization |
Version: | 1.10 → master |
comment:9 by , 8 years ago
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.
comment:10 by , 8 years ago
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.
Edit: This might be helpful https://code.djangoproject.com/ticket/20032
comment:11 by , 8 years ago
Owner: | changed from | to
---|---|
Status: | new → assigned |
comment:13 by , 8 years ago
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 a Django project's 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.
follow-up: 15 comment:14 by , 8 years ago
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.
comment:15 by , 8 years ago
Resolution: | → wontfix |
---|---|
Status: | assigned → closed |
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 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 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.
comment:16 by , 8 years ago
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.
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.