Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Code to run in all views in a views.py file

What would be the best way of putting a bit of code to run for all views in a views.py file?

I come from a PHP background and I normally put this in the constructor/index bit so that it always ran whatever page is being requested. It has to be specific for that views.py file though, I want to check that the user has access to 'this app/module' and want to avoid having to use decorators on all views if possible?

like image 474
user2355278 Avatar asked Jan 12 '23 18:01

user2355278


2 Answers

TL;DR

You should check about middlewares. It allows to execute some code before the view execution, the template rendering and other stuff.

Some words about middlewares

You can represent middlewares in your head like this:

Middleware concept

As you can see, the request (orange arrow) go through every middleware before executing the view and then can hitting every middleware after (if you want to do something before the template processing for example).

Using Django 1.10

Arcitecture of middlewares have changed in Django 1.10, and are now represented by simple function. For example, here's a counter of visits for each page:

def simple_middleware(get_response):
    # One-time configuration and initialization.

    def middleware(request):
        try:
            p = Page.objects.get(url=request.path)
            p.nb_visits += 1
            p.save()
        except Page.DoesNotExist: 
            Page(url=request.path).save() 

        response = get_response(request)
        if p:
            response.content += "This page has been seen {0} times.".format(p.nb_visits)

        return response

    return middleware

And voilà.

Using Django

Here's an example of middleware, which would update a counter for each visit of a page (admit that a Page Model exists with two field : url and nb_visits)

class StatsMiddleware(object):
    def process_view(self, request, view_func, view_args, view_kwargs):
        try:
            p = Page.objects.get(url=request.path)
            p.nb_visits += 1
            p.save()
        except Page.DoesNotExist: 
            Page(url=request.path).save() 

    def process_response(self, request, response):
        if response.status_code == 200:
            p = Page.objects.get(url=request.path)
            # Let's say we add our info after the html response (dirty, yeah I know)
            response.content += u"This page has been seen {0} times.".format(p.nb_visits)
        return response

Hopes this will help you :)

like image 97
Maxime Lorant Avatar answered Jan 20 '23 09:01

Maxime Lorant


Middleware is the solution but keep in mind the the order to define the middleware in the settings.py matters.

like image 34
Kintarō Avatar answered Jan 20 '23 08:01

Kintarō