#28491 closed Uncategorized (invalid)
"TypeError: context must be a dict rather than Context" when using loader.select_template() with Context
Reported by: | Mark Jones | Owned by: | nobody |
---|---|---|---|
Component: | Template system | Version: | 1.11 |
Severity: | Normal | Keywords: | |
Cc: | Triage Stage: | Unreviewed | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
The render method of the Template class looks like this
def render(self, context=None, request=None): context = make_context(context, request, autoescape=self.backend.engine.autoescape) try: return self.template.render(context) except TemplateDoesNotExist as exc: reraise(exc, self.backend)
The docs show this:
>>> from django.template import Context, Template >>> template = Template("My name is {{ my_name }}.") >>> context = Context({"my_name": "Adrian"}) >>> template.render(context) "My name is Adrian." >>> context = Context({"my_name": "Dolores"}) >>> template.render(context) "My name is Dolores."
However make_context looks like this (and throws an exception because of it):
if context is not None and not isinstance(context, dict): raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__) if request is None: context = Context(context, **kwargs) else: # The following pattern is required to ensure values from # context override those from template context processors. original_context = context context = RequestContext(request, **kwargs) if original_context: context.push(original_context) return context
I think it needs this code placed before the original code in make_context
if isinstance(context, Context): return context
so that if an actual context is passed in, it works as documented.
This bug only comes about when you select a template using code that looks like this:
from django.template import loader, Context servertemplate = loader.select_template(["deployment/%s" % options['webserver'], "deployment/default_%s" % options['webserver']])
because the loader returns an instance of <class 'django.template.backends.django.Template'> instead of <class 'django.template.base.Template'> which has a different render method that causes this problem.
My change does fix the issue, but I'm not sure if this is the right fix, or if there should be another.
Change History (3)
comment:1 by , 7 years ago
comment:2 by , 7 years ago
Resolution: | → invalid |
---|---|
Status: | new → closed |
I see you moved the conversation to ticket:27258#comment:12 and 13. Another possibility to fix your code would be to adapt the approach from #27722 like this:
servertemplate = loader.select_template(...).template
This won't work if you use any template engine besides the DjangoTemplates
but your comment suggests you don't care about that.
If you have some other suggestion of a code or documentation change to make, feel free to reopen the ticket.
comment:3 by , 7 years ago
Summary: | TypeError: context must be a dict rather than Context. → "TypeError: context must be a dict rather than Context" when using loader.select_template() with Context |
---|
To fix your code, you should indeed call
render()
with a plaintdict
rather than aContext
.This is related to a change in Django 1.11 (#27258). Does some documentation need clarification?