How to Create Restricted Views in Djangoby Owais Mushtaq
Very often, we may need to run a piece of code on each and every request that Django handles. For example, this code might need to modify the request before the viewer handles it, or log information about the request for debugging purposes, or limiting a set of users.
Middleware is a framework for inserting values in django request and response header. It’s light weight and its easy process allows to make user defined values have global access. This can help in limiting access for certain type of users.
In django, Middleware class can be activated by adding the middleware tuple to the settings file.
MIDDLEWARE_CLASSES = ( 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.common.CommonMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.auth.middleware.SessionAuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'django.middleware.clickjacking.XFrameOptionsMiddleware', 'django.middleware.security.SecurityMiddleware', )
The order of the middleware classes matters. The Authentication Middleware can’t be used before CacheMiddleware, because cache is created after authentication. And during the response phase, middleware are applied in reverse order, from the bottom up. This means classes defined at the end of MIDDLEWARE CLASSES will be run first.
How to hook the middleware with the your application:
There are two hooks available during the request phase before calling the view where we can implement Middleware classes.
During the response phase we have three hooks available.
Whenever there is a request in django to a view, it has to first pass through the process_request where django decides which view to call. For example, to know which user is logged in and if we have to limit him/her for accessing some value, we will need to append some info in the request (Http Request object) header so that when the django passes the request to a defined view.
Then we can limit the user by checking the request header.
Process_view(request, view_func, view_args, view_kwargs):
It is called just before django calls the view, or we can say after the process_request is called. It returns the HttpResponse object or None. If it returns None then Django will process remaining process_request’s and call a appropriate view and if it returns the HttpResponse object then Django can call any other desired view or exception middleware(process_exception).The response result will be appended to the HttpResponse object.
process_template_response(request, response): This is called after the view has finished processing and the view should have a response object that should be passed to a template using the render() method.
The process_template_response middleware can be used to redirect control to other template or changing the context dictionary values or make an entire new context dictionary.
Process_response(request, response): This is called on all responses before returned to browser that is, it is also called during process_request() and process_view() because they also can return HttpResponse object.It must return HttpResponse or StreamingHttpResponse() object.
Process_exception(request, exception) exception is an Exception object raised by the view function.Django calls process_exception() when a view raises an exception.
Process_exception() should return either None or an HttpResponse object. If it returns an HttpResponse object, the template response and response middleware will be applied, and the resulting response returned to the browser. Otherwise, default exception handling kicks in.
Implementation example for creating a limited view :
In Apps middleware.py
class LimitedCountryMiddleware(object): def process_request(self, request): #process_request() middleware class called if request.user.is_authenticated():# checking for autherization from dbank.api import CountryLimitedAccessResource # importing the api request.user.dqs_profile.is_limited=False country_limit = CountryLimitedAccessResource() limited = country_limit._get(vpd_id=request.user.dqs_profile.vpd_id, country='United States') if limited.exists():# checking for a condition if the api returns the object request.user.dqs_profile.is_limited=True #adding request header a variable
How Does the above example work:
- We define a middleware class.
- We define process_request middleware method.
- We perform some actions for getting object where the user is from United States.
- We hook the response object with limited boolean variable.
- Then we can check in any view or template if the user is limited, that is if limited is True then we can limit his view of template e.g. we will not show him addresses in template.
This way you can create restricted views in Django.