Opened 8 years ago

Closed 8 years ago

Last modified 8 years ago

#27722 closed Bug (fixed)

if a template context is an instance of get_template(), it will raise "TypeError: context must be a dict rather than RequestContext" — at Version 5

Reported by: Sayid Munawar Owned by: nobody
Component: Template system Version: 1.11
Severity: Release blocker Keywords:
Cc: FunkyBob, Aymeric Augustin Triage Stage: Accepted
Has patch: yes Needs documentation: no
Needs tests: no Patch needs improvement: no
Easy pickings: no UI/UX: no

Description (last modified by Sayid Munawar)

This simple view:

from django.views.generic import TemplateView
from django.template.loader import get_template

class Ngopi(TemplateView):
    template_name = 'base.html'

    def get_context_data(self, **kwargs):
        context = super(Ngopi, self).get_context_data(**kwargs)
        context.update({
            'menu': get_template('menu.html')
            })
        return context

with base.html:

<html>
	<body>
		<h1>Ngeteh</h1>
		{% include menu %}
	</body>
</html>

and menu.html:

<ul>
	<li>Ngeteh</li>
	<li>Ngopi</li>
</ul>

This situation will raise this exception:

Traceback (most recent call last):
  File "/Users/ayik/Repo/Django/django/django/core/handlers/exception.py", line 38, in inner
    response = get_response(request)
  File "/Users/ayik/Repo/Django/django/django/core/handlers/base.py", line 217, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/Users/ayik/Repo/Django/django/django/core/handlers/base.py", line 215, in _get_response
    response = response.render()
  File "/Users/ayik/Repo/Django/django/django/template/response.py", line 107, in render
    self.content = self.rendered_content
  File "/Users/ayik/Repo/Django/django/django/template/response.py", line 84, in rendered_content
    content = template.render(context, self._request)
  File "/Users/ayik/Repo/Django/django/django/template/backends/django.py", line 66, in render
    return self.template.render(context)
  File "/Users/ayik/Repo/Django/django/django/template/base.py", line 207, in render
    return self._render(context)
  File "/Users/ayik/Repo/Django/django/django/template/base.py", line 199, in _render
    return self.nodelist.render(context)
  File "/Users/ayik/Repo/Django/django/django/template/base.py", line 990, in render
    bit = node.render_annotated(context)
  File "/Users/ayik/Repo/Django/django/django/template/base.py", line 957, in render_annotated
    return self.render(context)
  File "/Users/ayik/Repo/Django/django/django/template/loader_tags.py", line 212, in render
    return template.render(context)
  File "/Users/ayik/Repo/Django/django/django/template/backends/django.py", line 64, in render
    context = make_context(context, request, autoescape=self.backend.engine.autoescape)
  File "/Users/ayik/Repo/Django/django/django/template/context.py", line 285, in make_context
    raise TypeError('context must be a dict rather than %s.' % context.__class__.__name__)
TypeError: context must be a dict rather than RequestContext.

This is fine with django 1.10, but not master (mine is currently 1.11.dev20170109230310)

a quick workaround is to edit django/template/backends/django.py Line 63 to be like this:

    def render(self, context=None, request=None):
        if isinstance(context, dict):  # <-- my temporary workaround
            context = make_context(context, request, autoescape=self.backend.engine.autoescape)
        try:
            return self.template.render(context)
        except TemplateDoesNotExist as exc:
            reraise(exc, self.backend)

Change History (5)

comment:1 by Tim Graham, 8 years ago

Does get_template() create some behavior difference as opposed to context.update({'menu': 'menu.html'})? See #27258 for the reason this error was added. Your proposed change effectively removes that fix.

Last edited 8 years ago by Tim Graham (previous) (diff)

comment:2 by Sayid Munawar, 8 years ago

Resolution: fixed
Status: newclosed

sorry Tim, my proposed change didn't mean to really fix the problem, just a workaround so that i can continue to code.

using context.update({'menu': 'menu.html'}) solved my problem. it just weird since it was working fine until 1.10

comment:3 by Tim Graham, 8 years ago

Resolution: fixedwontfix

It's allowed to call {% include %} with a django.template.base.Template but not django.template.backends.django.Template (added in 5cdacbda034af928f5033c9afc7b50ee0b13f75c).

Last edited 8 years ago by Tim Graham (previous) (diff)

comment:4 by Tim Graham, 8 years ago

Cc: FunkyBob added

Curtis, as the author of 5cdacbda034af928f5033c9afc7b50ee0b13f75c, I wonder if you have any input here? I'm not happy that I broke backwards compatibility (due to #27258) with such a cryptic error message here. At least the {% include %} docs that say, "The variable may also be any object with a render() method that accepts a context." might need some clarification.

The use case is described in the django-material issue.

comment:5 by Sayid Munawar, 8 years ago

Description: modified (diff)
Note: See TracTickets for help on using tickets.
Back to Top