#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 , 16 years ago
comment:2 by , 16 years ago
| Version: | 1.1 → SVN |
|---|
comment:3 by , 16 years ago
| Triage Stage: | Unreviewed → Accepted |
|---|
comment:4 by , 16 years ago
| Resolution: | → fixed |
|---|---|
| Status: | new → closed |
Changing the new loader's
load_templateto: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_originis then passed when the template source is compiled viaget_template_from_string, inget_template. For the new loader the return value from thatmake_origincall infind_templateis never used, sinceget_templatedetermines the returned tempalte value has already been compiled. This is good since that call tomake_originfor 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.