#12992 closed (fixed)
New template loaders lose debug information
Reported by: | Karen Tracey | Owned by: | nobody |
---|---|---|---|
Component: | Template system | Version: | dev |
Severity: | Keywords: | ||
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
For a TemplateSyntaxErorr, if you have the new-style template loaders in settings.py
:
TEMPLATE_LOADERS = ( 'django.template.loaders.filesystem.Loader', 'django.template.loaders.app_directories.Loader', # 'django.template.loaders.eggs.Loader', )
The Template error
section of the debug page doesn't report the name of the template file where the problem occurred. Instead it reports In template <unknown source>, error at line <whatever>
. One problem is the angle brackets aren't displayed properly but the real problem is that the source file name is "unknown".
Problem is due to the new-style loader's returning already-compiled templates (from http://code.djangoproject.com/browser/django/trunk/django/template/loader.py#L36):
def __call__(self, template_name, template_dirs=None): return self.load_template(template_name, template_dirs) def load_template(self, template_name, template_dirs=None): source, origin = self.load_template_source(template_name, template_dirs) template = get_template_from_string(source, name=template_name) return template, origin
The old loaders return the source, origin
as originally returned by load_template_source
, and the template source is compiled into a <django.template.Template>
when get_template
finds what it got doesn't have a render
(from http://code.djangoproject.com/browser/django/trunk/django/template/loader.py#L139):
def get_template(template_name): """ Returns a compiled Template object for the given template name, handling template inheritance recursively. """ template, origin = find_template(template_name) if not hasattr(template, 'render'): # template needs to be compiled template = get_template_from_string(template, origin, template_name) return template
That call to get_template_from_string
includes the origin, which is what is needed to report the file name on the debug page.
Note origin
in this bit of code is different from the origin
returned by load_template_source
above. That part of the load_template_source
return value is called display_name
in other parts of the code and is one of four args passed to make_origin
to produce the origin
passed in to get_template_from_string
in the working path. So we cannot simply change the new-style loader code to pass the thing it calls origin
to get_template_from_string
. Nor does attempting to call make_origin
with likely-seeming args in the new-style loader code work, possibly because I don't really have a clue what those args are supposed to all be. What does work is:
def __call__(self, template_name, template_dirs=None): return self.load_template_source(template_name, template_dirs)
But I gather based on the doc here: http://docs.djangoproject.com/en/dev/ref/templates/api/#using-an-alternative-template-language that loaders are supposed to have a load_template
method that returns a pre-compiled template so it would probably be better for someone with a clue in this area to figure out how to get the origin information properly attached to the already-compiled template returned by the new-style loaders.
Change History (5)
comment:1 by , 15 years ago
comment:2 by , 15 years ago
Version: | 1.1 → SVN |
---|
comment:3 by , 15 years ago
Triage Stage: | Unreviewed → Accepted |
---|
comment:4 by , 15 years ago
Resolution: | → fixed |
---|---|
Status: | new → closed |
Changing the new loader's
load_template
to:fixes the problem of the missing template file name on the debug page, but this is kind of ugly. The old loaders are returning a tuple of template source and its file name, this 2nd element of the tuple is turned into an origin in
find_template
(from http://code.djangoproject.com/browser/django/trunk/django/template/loader.py#L120):and that return value from
make_origin
is then passed when the template source is compiled viaget_template_from_string
, inget_template
. For the new loader the return value from thatmake_origin
call infind_template
is never used, sinceget_template
determines the returned tempalte value has already been compiled. This is good since that call tomake_origin
for the new loader case doesn't produce an origin object capable of retrieving the template source, since it expects to be given a loader that returns the template source, not an already-compiled template. But it's ugly to have that useless call in the new path producing something that could never be usefully used.