New template loaders lose debug information
|Reported by:||kmtracey||Owned by:||nobody|
|Has patch:||no||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||no|
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 Changed 4 years ago by kmtracey
- Needs documentation unset
- Needs tests unset
- Patch needs improvement unset