django.get_template is returning a RequestContext, but render wants a dict?

So, this is quite weird to me. I wrote an app that worked fine on Django 1., and I had way too much fun trying to update it to work with Django 4.1 - and it still doesn’t work.

I’m getting the following error (which I have NOT found anywhere using DuckDuckGo OR google!):

 File "/usr/local/lib/python3.6/dist-packages/django/template/backends/django.py", line 59, in render
   context = make_context(context, request, autoescape=self.backend.engine.autoescape)
 File "/usr/local/lib/python3.6/dist-packages/django/template/context.py", line 268, 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.
[17/Sep/2022 13:08:43] "GET /home HTTP/1.1" 500 75180

Here’s (parts of) the code:

from django.http import HttpResponse, HttpResponseRedirect
from lunchpolls.models import *
from django.template import Context, loader, RequestContext, Template
...lots of code...
def home_processing(request,countvote):
   ...lots more code...
    t = loader.get_template("home.html")
    #t = Template("home.html")
    c = RequestContext(request, { 'user_logged_in':user_logged_in,
                                  'user_is_admin':user_is_admin,
                                  'message':message,
                                  'sortdir':sortdir,
                                  'restaurantlist':restaurantlist,
                                  'vote1':vote1,'vote2':vote2,
                                  'sortby':str(sortfield),
                                  'groupname':user_group_name,
                                  'group_message':gmsg,
                                  })
    c.update(csrf(request))
    return HttpResponse(t.render(c),request)

If I uncomment the Template line, the t.render(c) does not fail (and, of course, all I get is ‘home.html’ in my web browser - not the goal here! :smiley: )

I’ve spent a pretty good amount of time trying to figure out why it appears that get_template does not return the thing that render requires, even reading through (well, ok, skimming through) ALL the release notes from 2.0 to 4.1 (or maybe 4.2, its all a blur now).

I’m out of ideas. Help!

Notice what the error message is telling you.

Now look at where you’re creating a RequestContext, and change it to create a dict.

Or, you might just be better off reviewing the documentation in the tutorial as to how current django renders a template to return a response.

Well, I’m usually pretty good at decoding error messages, and I managed to mis-decode that one.

Actually, hold on, see this, taken from the CURRENT 4.1 documentation (Django 4.1 template api document):

Using RequestContext¶

class RequestContext(request, dict_=None, processors=None)¶

Django comes with a special Context class, django.template.RequestContext, that acts slightly differently from the normal django.template.Context. The first difference is that it takes an HttpRequest as its first argument. For example:

c = RequestContext(request, {
    'foo': 'bar',
})

So, a suggestion that I RTFM was less than helpful, since I did read it, and it SAYS that RequestContext is a special Context class. But apparently it isn’t a context?!?

And THAT is exactly why I posted this question in the first place.

Now, I’ll turn to the actual issue at hand.

Removing ‘RequestContext()’ fixes the problem.

That is, I just deleted the ‘RequestContext(request,’ (and the matching ‘)’ and it now works.

Thank you. I’ll shut up now before I get in any more trouble!

(Perhaps part of the problem is how overloaded the word ‘context’ seems to be here. I needed a ‘context’, but a ‘RequestContext’ wasn’t the right context!)

To try to (perhaps) clear some of the confusion -

First, I agree that the overloading of the term “context” doesn’t help matters much. Unfortunately, it’s not the only word that ends up with different meanings depending upon the area in which it’s being used. (I was going to say “… depending on the context in which …”, but fortunately I avoided doing that.)

Yes, a minor but significant detail, Context != context. Or in this case, the parameter being passed to the Template object is called the “context” for that Template, but that context is a dict and not a Context.

But the real reason for this post and my suggestion to review the tutorial docs is that you don’t typically see this pattern for rendering templates. Modern Django practices tend to favor using one or more of the shortcut functions.

e.g.

template = "home.html"
context = { 'user_logged_in': user_logged_in, 'user_is_admin': user_is_admin, ... }
return render(request, template, context)

(Side note: We also use render_to_string quite a bit too - it allows for a template to be rendered in the absence of a request, which we find useful in a number of different circumstances.)

Thank you very much for that clarification!

And, I was certain that I got that sequence (get_template(), RequestContext(), render()) from the (djangoproject) tutorial when I started (no idea where else I would have gotten it!), but I spent some time trying to find that tutorial so I could point it out, and couldn’t find it! But I did find an example at python - {% something %} syntax in django tutorial - Stack Overflow Hmm. Well, water under the bridge now :slight_smile:

I don’t suppose ‘we’ could add something to the RequestContxt documentation like:

Note that this RequestContext is not the same as the context you need to pass to render. If you somehow used it with a much older Django, simply remove the ‘RequestContex(request’ from your code (correcting the bad nesting).

For example, if you had written

   t = loader.get_template("home.html")
   c = RequestContext(request, { 'user_logged_in':user_logged_in,.....} )
   p = t.render(c)

Then you need to turn that:

 c = RequestContext(request, { 'user_logged_in':user_logged_in,.....} )

in to

 c = { 'user_logged_in':user_logged_in,.....} 

and you should be fine.

… end of suggested addition…

(And I promise to try very hard to quit making edits to this latest post!!!)