I am building a website using django 1.10. I have written a middleware class to restrict the number of page views for users that are not logged in. I implemented this functionality into a separate application 'pagerestrict'
settings.py [Relevant Entries]
# Application definition
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'django.contrib.sites',
'pagerestrict.apps.PagerestrictConfig',
# ...
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'pagerestrict.middleware.CheckPageAccessMiddleware',
]
Middleware code (middleware.py):
from django.http import HttpResponseRedirect
from decouple import config
class CheckPageAccessMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_request(self, request):
if not request.user.is_authenticated():
current_page_url = request.path_info.lstrip('/')
ignore_list = config('PAGE_RESTRICT_PAGE_IGNORES', cast=lambda v: [s.strip() for s in v.split(',')])
#if not current_page_url or not any(current_page_url != url for url in ignore_list):
if not current_page_url in ignore_list:
# first things first ...
if not has_attr(request, 'pages_visited'):
request.pages_visited = set()
if not has_attr(request, 'page_count'):
request.page_count = 0
if current_page_url not in request.pages_visited:
request.pages_visited.add(current_page_url)
request.page_count += 1
if request.page_count > config('PAGE_RESTRICT_PAGE_LIMIT'):
return HttpResponseRedirect(config('PAGE_RESTRICT_REDIRECT_URL'))
I tested this by going to my homepage and refreshing the browser several times - the code never seemed to be triggered. What am I missing?
Built-in Middleware are provided by default in Django when you create your project. You can check the default Middleware in settings.py file of your project. Custom Middleware — You can write your own middleware which can be used throughout your project.
In Django, middleware is a lightweight plugin that processes during request and response execution. Middleware is used to perform a function in the application. The functions can be a security, session, csrf protection, authentication etc.
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.
Middleware and decorators are similar and can do the same job. They provide a means of inserting intermediary effects either before or after other effects downstream in the chain/stack.
New-style middleware does not call process_request
and process_response
by default. This functionally has been replaced with __call__
and the get_response
function that is passed to __init__
.
You need to call process_request()
inside __call__
and process the return value if it is not None
. The easiest way to do this is to use the MiddlewareMixin
provided by Django. This will define the necessary __init__
and __call__
methods, and __call__
will call process_request()
and process_response()
if they are defined.
from django.utils.deprecation import MiddlewareMixin
class CheckPageAccessMiddleware(MiddlewareMixin):
def process_request(self, request):
if not request.user.is_authenticated():
current_page_url = request.path_info.lstrip('/')
ignore_list = config('PAGE_RESTRICT_PAGE_IGNORES', cast=lambda v: [s.strip() for s in v.split(',')])
#if not current_page_url or not any(current_page_url != url for url in ignore_list):
if not current_page_url in ignore_list:
# first things first ...
if not has_attr(request, 'pages_visited'):
request.pages_visited = set()
if not has_attr(request, 'page_count'):
request.page_count = 0
if current_page_url not in request.pages_visited:
request.pages_visited.add(current_page_url)
request.page_count += 1
if request.page_count > config('PAGE_RESTRICT_PAGE_LIMIT'):
return HttpResponseRedirect(config('PAGE_RESTRICT_REDIRECT_URL'))
I finally got this to work. It was based on the Middleware topic on the now defunct Stack Overflow Documentation site. (Attribution details can be found on the contributor page. Reference topic ID: 1721.)
from django.http import HttpResponseRedirect
from decouple import config
class CheckPageAccessMiddleware(object):
def __init__(self, next_layer=None):
"""We allow next_layer to be None because old-style middlewares
won't accept any argument.
"""
self.get_response = next_layer
def process_request(self, request):
"""Let's handle old-style request processing here, as usual."""
# Do something with request
# Probably return None
# Or return an HttpResponse in some cases
if not request.user.is_authenticated():
current_page_url = request.path_info.lstrip('/')
print ('Current page url: {0}'.format(current_page_url))
root_url = '' # root url == ('')
restrict_redirect_page = config('PAGE_RESTRICT_REDIRECT_URL')[1:] # chop of leading '/'
ignore_list = [root_url, restrict_redirect_page] + \
config('PAGE_RESTRICT_PAGE_IGNORES', cast=lambda v: [s.strip() for s in v.split(',')])
print('ignore list: %s' % ",".join([x for x in ignore_list]))
#if not current_page_url or not any(current_page_url != url for url in ignore_list):
if not current_page_url in ignore_list:
# first things first ...
if 'pages_visited' not in request.session:
request.session['pages_visited'] = ''
if 'page_count' not in request.session:
request.session['page_count'] = 0
pages_visited = [x.strip() for x in request.session['pages_visited'].split(',')]
if current_page_url not in pages_visited:
pages_visited.append(current_page_url)
request.session['pages_visited'] = ",".join(x.strip() for x in pages_visited)
request.session['page_count'] += 1
print('Request page count: {0}'.format(request.session['page_count']))
if request.session['page_count'] > config('PAGE_RESTRICT_PAGE_LIMIT', cast=int):
return HttpResponseRedirect(config('PAGE_RESTRICT_REDIRECT_URL'))
return None
def process_response(self, request, response):
"""Let's handle old-style response processing here, as usual."""
# Do something with response, possibly using request.
return response
def __call__(self, request):
"""Handle new-style middleware here."""
response = self.process_request(request)
if response is None:
# If process_request returned None, we must call the next middleware or
# the view. Note that here, we are sure that self.get_response is not
# None because this method is executed only in new-style middlewares.
response = self.get_response(request)
response = self.process_response(request, response)
return response
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With