noisebridge / pyclass-project

Other
8 stars 2 forks source link

Header not displaying logged in user on all pages #16

Closed Belgand closed 12 years ago

Belgand commented 12 years ago

Not all pages are showing that a user is logged in, instead displaying the "log in" link. Currently the only pages that show that you're logged in are those under /accounts/ (e.g. login, register, etc.) and add interest. Search and, most importantly, Home don't.

Belgand commented 12 years ago

The problem turned out to be pretty simple actually. In order to trigger the {% if user.is_authenticated %} block the variable "user" actually needs to be in the template's context (the dictionary of keys and values that a template has access to). The pages that weren't working didn't have it defined. So why did "add interest"? Because django is smarter than me.

In order to get csrf to work properly I ended up having to add context_instance=RequestContext(request) as the third argument to render_to_response(). When we use the render_to_response() shortcut it uses a standard Context object and this turned out to be the crux of the problem. RequestContext, unlike the basic Context class calls a set of context processors defined in the TEMPLATE_CONTEXT_PROCESSORS setting of settings.py. In a nutshell context processors take a request object as their argument and return a dictionary of items to be merged into the context. The upshot is that this gives us a set of common variables that can be utilized in our templates. This includes "user" and the token needed by {% csrf_token %} among others. A fuller description of context processors and all the variables that this will add into the context is available in the Django docs under The Django template language: For Python programmers. This provides a bunch of useful information about working with templates and I suggest everyone who hasn't read it to read over it.

While we could just add RequestContext as an argument to render_to_response the even easier option is to just switch to using render() which will use RequestContext instead of Context. It takes a request object as a required argument, but otherwise its usage is exactly the same.

For reference this function is detailed in the Django docs at Django shortcut functions.

TL;DR version: It was failing because render_to_response() uses Context not RequestContext and we didn't have the right variables in our context as a result. To keep things from breaking going forward please change from using render_to_response() in favor of render(). The format is:

from django.shortcuts import render

... view code ...

return render(request,
                         'my_template.html',
                         my_data_dictionary)

to render templates. Be certain that you aren't using any of the variable names that the context processors want to use or they'll overwrite them.