PT114
PT114

Reputation: 951

Setting a variable in middleware to be accessed in the template

I seem to be having difficulty setting a variable in one of my middleware classes that I can then access in the template layer.

The basic layout is this:

class TheMiddleware(object):
    def __init__(self, etc):
        stuff...

    def process_response(self, request, response):
        request.my_var = "whatever"
        return response

Then on the template for a different view I have:

{% custom_tag arg_a %}

Which is is a template tag that should return the variable from the request:

@register.simple_tag
def custom_tag(arg_a):
    return threading.currentThread().request.my_var

This errors out with "Caught AttributeError while rendering: 'WSGIRequest' object has no attribute 'my_var'"

I thought it might be the way I was accessing the request in the template tag. So I added django.core.context_processors.request to my TEMPLATE_CONTEXT_PROCESSORS as in This question and tried passing the request object to the tag, then accessing request directly from the template but with no luck.

I think I lack an understanding on how request objects work. Is it possible to assign a variable to a request object and pick that variable up several views on? I thought the request object was passed through the views, but it seems that instead a new instance is generated.

If that is the case, how would you go about storing a global variable within middleware that you could then access from any point in your app, be it in a view or a template?

Update:

To clear up the confusion (whether mine or others I'm not sure!) I'm not trying to set the request variable in the process_response middleware of a view and then pick it up in the template of that same view. I understand that that wouldn't work because the template has been processed before the variable is saved. (This is a deliberate act on my part).

I have two views, view1 and view2 view one has a decorator that causes the middleware to set the variable in the request. It is the view2 template, which comes after the variable has been set, that I wish to access the variable.

Upvotes: 8

Views: 9078

Answers (2)

Rohan
Rohan

Reputation: 53326

You trying to set variable during processing of response in your middleware.

I think you should be implementing process_request() instead to set the variable.

def process_request(self, request):
    request.my_var = "whatever"
    return 

Upvotes: 10

Daniel Roseman
Daniel Roseman

Reputation: 599600

If you're setting it on the request, I can't see any reason at all to try and use threadlocals here. You should use the context processor as you describe.

The reason for your problem, though, is that process_response is run in the response phase of the request/response cycle: ie, after your view has been called. You should define process_request instead. See here for a description of the order that middleware methods are called.

Upvotes: 3

Related Questions