Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django - having middleware communicate with views/templates

Tags:

python

django

Alright, this is probably a really silly question but I am new to Python/Django so I can't really wrap my head around its scoping concepts just yet. Right now I am writing a middleware class to handle some stuff, and I want to set 'global' variables that my views and templates can access. What is the "right" way of doing this? I considered doing something like this:

middleware.py

from django.conf import settings

class BeforeFilter(object):
    def process_request(self, request):
        settings.my_var = 'Hello World'
        return None

views.py

from django.conf import settings
from django.http import HttpResponse

def myview(request):
    return HttpResponse(settings.my_var)

Although this works, I am not sure if it is the "Django way" or the "Python way" of doing this.

So, my questions are:
1. Is this the right way?
2. If it is the right way, what is the right way of adding variables that can be used in the actual template from the middleware? Say I want to evaluate something and I want to set a variable headername as 'My Site Name' in the middleware, and I want to be able to do {{ headername }} in all templates. Doing it the way I have it now I'd have to add headername to the context inside every view. Is there anyway to bypass this? I am thinking something along the lines of CakePHP's $this->set('headername','My Site Name');
3. I am using the middleware class as an equivalent of CakePHP's beforeFilter that runs before every view (or controller in CakePHP) is called. Is this the right way of doing this?
4. Completely unrelated but it is a small question, what is a nice way of printing out the contents of a variable to the browser ala print_r? Say I want to see all the stuff inside the request that is passed into the view? Is pprint the answer?

like image 609
Paolo Bergantino Avatar asked Feb 17 '09 15:02

Paolo Bergantino


People also ask

What can be achieved using middleware in Django?

You can use middleware if you want to modify the request i.e HttpRequest object which is sent to the view. Or you might want to modify the HttpResponse object returned from the view. Both these can be achieved by using a middleware. You might want to perform an operation before the view executes.

What is the purpose of middleware in Django?

Middleware is a framework of hooks into Django's request/response processing. It's a light, low-level “plugin” system for globally altering Django's input or output. Each middleware component is responsible for doing some specific function.

What is {% include %} in Django?

The include tag allows you include a template inside the current template. This is useful when you have a block of content that are the same for many pages.

Can we create custom middleware in Django?

Custom middleware in Django is created either as a function style that takes a get_response callable or a class-based style whose call method is used to process requests and responses. It is created inside a file middleware.py . A middleware is activated by adding it to the MIDDLEWARE list in Django settings.


2 Answers

  1. It's not the best way. You could set my_var on the request rather than on the settings. Settings are global and apply to the whole site. You don't want to modify it for every request. There could be concurrency issues with multiple request updating/reading the variable at the same time.

  2. To access request.my_var in your templates you could do {{ request.my_var }}. To get access to the request variable in your template you will have to add django.core.context_processors.request to your TEMPLATE_CONTEXT_PROCESSORS setting.

  3. Yes. Other terminology to describe request middleware would be request pre-processor/filter/interceptor.

Also, if you want to use a common Site name for the header in your templates, you might want to check out the Django Sites application which provides a site name variable for your use.

like image 59
Akbar ibrahim Avatar answered Sep 23 '22 16:09

Akbar ibrahim


Here's what we do. We use a context processor like this...

def context_myApp_settings(request):
    """Insert some additional information into the template context
    from the settings.
    Specifically, the LOGOUT_URL, MEDIA_URL and BADGES settings.
    """
    from django.conf import settings
    additions = {
        'MEDIA_URL': settings.MEDIA_URL,
        'LOGOUT_URL': settings.LOGOUT_URL,
        'BADGES': settings.BADGES,
        'DJANGO_ROOT': request.META['SCRIPT_NAME'],
    }
    return additions

Here the setting that activates this.

TEMPLATE_CONTEXT_PROCESSORS = (
    "django.core.context_processors.auth",
    "django.core.context_processors.debug",
    "django.core.context_processors.i18n",
    "django.core.context_processors.media",
    "django.core.context_processors.request",
    "myapp. context_myApp_settings",
    )

This provides "global" information in the context of each template that gets rendered. This is the standard Django solution. See http://docs.djangoproject.com/en/dev/ref/templates/api/#ref-templates-api for more information on context processors.


"what is a nice way of printing out the contents of a variable to the browser ala print_r?"

In the view? You can provide a pprint.pformat string to a template to be rendered for debugging purposes.

In the log? You have to use Python's logging module and send stuff to a separate log file. The use of simple print statements to write stuff to the log doesn't work wonderfully consistently for all Django implementations (mod_python, for example, loses all the stdout and stderr stuff.)

like image 43
S.Lott Avatar answered Sep 21 '22 16:09

S.Lott