Middleware Setup - django

I am trying to setup a message middleware for my marketing app,but the method process_request is not returning anything.
it is running without errors still though not returning message requests.
my middleware.py---
from .models import MarketingMessage
class DisplayMarketing():
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
def process_request(request):
print("something")
try:
request.session['marketing_message'] = MarketingMessage.objects.all()[0].message
except:
request.session['marketing_message'] = False
response = self.get_response(request)
return response
my settings.py
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',
'marketing.middleware.DisplayMarketing',
]

if you use middleware mixin process_request will automatically called.
try
from django.utils.deprecation import MiddlewareMixin
class DisplayMarketing(MiddlewareMixin):
def __init__(self, get_response):
self.get_response = get_response
def process_request(self, request):
print("something")
try:
request.session['marketing_message'] = "bossk"
except:
request.session['marketing_message'] = False
or, other wise you have call process_request manually
from .models import MarketingMessage
class DisplayMarketing():
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
def process_request(request):
print("something")
try:
request.session['marketing_message'] ="bossk"
except:
request.session['marketing_message'] = False
response = self.get_response(process_request(request))
return response

Related

Django Success URL Gets Appended To Middleware Redirect URL Instead of Redirecting To Success URL

I have a form with a username field on it located at /accounts/choose-username/.
views.py
from django.views.generic import FormView
from .forms import ChooseUsernameForm
from django.contrib.auth import get_user_model
User = get_user_model()
class ChooseUsernameView(FormView):
template_name = 'registration/choose-username.html'
form_class = ChooseUsernameForm
success_url = 'accounts/profile/' # <-------------
def form_valid(self, form):
"""If the form is valid, redirect to the supplied URL."""
print(form.cleaned_data['username'])
print(self.request.user)
user = User.objects.get(email=self.request.user)
user.username = form.cleaned_data['username']
user.save()
return super().form_valid(form)
middleware.py
from django.shortcuts import redirect, reverse
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
# One-time configuration and initialization.
def __call__(self, request):
# Code to be executed for each request before
# the view (and later middleware) are called.
response = self.get_response(request)
if request.user.is_authenticated:
if request.user.username is None:
print(request.path)
if not request.path == reverse('choose_username'):
return redirect(reverse('choose_username'))
return response
When I submit the form, my url is accounts/choose-username/accounts/profile/
I want it to be accounts/profile/
MIDDLEWARE settings.py looks like this:
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.common.CommonMiddleware',
'accounts.middleware.SimpleMiddleware', # <---
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]
My Question
Why does my success URL get appended to my accounts/choose-username/ URL? How can I fix it?
As this—accounts/profile/—doesn't start with a slash (/), so it is a relative path. Browsers automatically append the relative path to the current page's url.
You need to use absolute path (add slash in the beginning).
success_url = '/accounts/profile/'

Middleware not executed by Django

I am trying to include a middleware in a Django project, but it seems the middleware is not being executed by Django. The idea is to impersonate another user account when having app-administrator privileges.
The MIDDLEWARE section of my settings.py file looks like this:
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',
'mird_project.monitor.middleware.impersonateMiddleware.ImpersonateMiddleware',
]
The middleware class looks like this:
from .models import Usuario
class ImpersonateMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_request(self, request):
us_obj = Usuario.objects.all().filter(id_usuario=request.user.username).first()
tipo = us_obj.tipo.id_tipo
if tipo == "AD" and "__impersonate" in request.GET:
request.session['impersonate_id'] = request.GET["__impersonate"]
elif "__unimpersonate" in request.GET:
del request.session['impersonate_id']
if tipo == "AD" and 'impersonate_id' in request.session:
request.user = Usuario.objects.get(id_usuario=request.session['impersonate_id'])
return None
I inserted an assert False, request inside the process_request method so that it would abort execution with an exception and show me what request contained. It never even got executed, so I assume the middleware never gets executed. It doesn't throw any kind of error and the impersonation mechanism just displays the same administrator user in the site.
Any ideas why the middleware isn't being called?
It looks like you are mixing old and new style middleware APIs. The process_request() method is pre-Django 1.10 and won't get called automatically unless your middleware class uses MiddlewareMixin.
You'll need to call process_request() yourself from the __call__() method:
def __call__(self, request):
self.process_request(request) # Call process_request()
response = self.get_response(request)
return response
Or alternatively you could inherit from MiddlewareMixin so that process_request() is called by Django. However it would only make sense to do that if you need to make the middleware backwards compatible.

Issue with Django 2.0 : 'WSGIRequest' object has no attribute 'session'

I upgraded my Django version from 1.11.5 to 2.0 and I'm trying to solve different deprecated element.
However, even if my CSS/bootstrap style sheet doesn't work, I don't overcome to log into my Django software. I have this issue :
'WSGIRequest' object has no attribute 'session'
This is the entire Traceback :
Environment:
Request Method: POST
Request URL: http://127.0.0.1:8000/Authentification/Login/
Django Version: 2.0
Python Version: 3.6.2
Installed Applications:
['Institution',
'django.conf.urls',
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'bootstrapform',
'django_countries',
'chartit',
'Configurations',
'Home',
'Authentication',
'Identity',
'rest_framework',
'Fiscal',
'bootstrap4']
Installed Middleware:
[]
Traceback:
File "/Users/valentinjungbluth/Desktop/DatasystemsCORE3.6/lib/python3.6/site-packages/django/core/handlers/exception.py" in inner
35. response = get_response(request)
File "/Users/valentinjungbluth/Desktop/DatasystemsCORE3.6/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
128. response = self.process_exception_by_middleware(e, request)
File "/Users/valentinjungbluth/Desktop/DatasystemsCORE3.6/lib/python3.6/site-packages/django/core/handlers/base.py" in _get_response
126. response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "/Users/valentinjungbluth/Desktop/DatasystemsCORE3.6/lib/python3.6/site-packages/django/views/decorators/csrf.py" in wrapped_view
54. return view_func(*args, **kwargs)
File "/Users/valentinjungbluth/Desktop/Django/DatasystemsCORE/DatasystemsCore/DatasystemsCORE/Authentication/views.py" in Login
26. login(request, user)
File "/Users/valentinjungbluth/Desktop/DatasystemsCORE3.6/lib/python3.6/site-packages/django/contrib/auth/__init__.py" in login
130. if SESSION_KEY in request.session:
Exception Type: AttributeError at /Authentification/Login/
Exception Value: 'WSGIRequest' object has no attribute 'session'
In my Authentification app :
# views.py file
#-*- coding: utf-8 -*-
from django.contrib.auth import authenticate, login, logout
from .forms import ConnexionForm
from django.shortcuts import render, reverse, get_object_or_404, redirect
from django.http import HttpResponseRedirect, HttpResponse
from .models import LoggedUsers
from API_GED import Logger
import datetime
from django.views.decorators.csrf import csrf_exempt,csrf_protect
#csrf_exempt
def Login(request):
error = False
if request.method == "POST":
form = ConnexionForm(request.POST)
if form.is_valid():
username = form.cleaned_data["username"]
password = form.cleaned_data["password"]
user = authenticate(username=username, password=password) # Nous vérifions si les données sont correctes
if user: # Si l'objet renvoyé n'est pas None
login(request, user)
response = redirect('Homepage')
return response
else: # sinon une erreur sera affichée
error = True
else:
form = ConnexionForm()
return render(request, 'Authentication_Homepage.html', locals())
def Logout(request):
logout(request)
return redirect(reverse('Choice'))
def ConnectedUsers(request) :
logged_users = LoggedUsers.objects.all()
print (logged_users)
logged_users_number = LoggedUsers.objects.all().count()
context = {
"logged_users":logged_users,
"logged_users_number":logged_users_number,
}
return render(request, "Authentication_LoggedUsers.html", context)
An my models.py file :
from django.db import models
from django.contrib.auth.models import User
from django.contrib.auth.signals import user_logged_in, user_logged_out
# class UserProfile(models.Model):
# user = models.OneToOneField(User)
# avatar = models.ImageField(upload_to='/images/')
class LoggedUsers(models.Model):
user = models.ForeignKey(User, primary_key=True, on_delete=models.CASCADE)
def __str__(self):
return '{}{}{}'.format(self.user.first_name + " ", self.user.last_name + " (", self.user.username + ")")
def login_user(sender, request, user, **kwargs):
LoggedUsers(user=user).save()
def logout_user(sender, request, user, **kwargs):
try:
u = LoggedUsers.objects.get(user=user)
u.delete()
except LoggedUsers.DoesNotExist:
pass
user_logged_in.connect(login_user)
user_logged_out.connect(logout_user)
In my settings.py file, I have MIDDLEWARE_CLASSES :
MIDDLEWARE_CLASSES = [
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.middleware.gzip.GZipMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
'django.middleware.security.SecurityMiddleware',
'DatasystemsCORE.middleware.OnlineNowMiddleware',
]
Any idea ?
EDIT :
I wrote MIDDLEWARE like this :
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',
]
It seems to work !
So the MIDDLEWARE_CLASSES changed to MIDDLEWARE https://docs.djangoproject.com/en/2.0/topics/http/middleware/#activating-middleware
MIDDLEWARE_CLASSES has been deprecated since Django 1.10 and was removed completely in version 2.0. That means you have no middleware at all.
You should use the MIDDLEWARE setting instead; note, that uses new-style middleware, you might need to upgrade your custom middleware class.

django - why is this custom middleware not working

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?
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
You can change import like this:
try:
from django.utils.deprecation import MiddlewareMixin
except ImportError:
MiddlewareMixin = object
Here is an example to show how to update the middleware when migrating to
Django ver > 1.10:
Upgrading pre-Django 1.10-style middleware
If it does not work:
You should also temporarily remove all default MIDDLEWARE class,
keeping only your custom MIDDLEWARE to make sure the previous
layers(default MIDDLEWARE) did not break the flow:
MIDDLEWARE = (
# 'django.middleware.common.CommonMiddleware',
'app.middleware.MyMiddlewareClass',
)
If you remove django.middleware.common.CommonMiddleware then it works. That could be ALLOWED_HOSTS problem.
- Replace
ALLOWED_HOSTS= ['localhost:8001']
- With
ALLOWED_HOSTS= ['localhost']
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.NYou need to call process_request() inside call and
process the return value if it is not None.
So you can write the code that you want to put into process_request() method to call() as below:
from django.http import HttpResponseRedirect
from decouple import config
class CheckPageAccessMiddleware(object):
def __init__(self, next_layer=None):
self.get_response = next_layer
def __call__(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'))

Django exception middleware: TypeError: object() takes no parameters

I'm using Django 1.10 and trying to catch all exceptions with exception middleware.
The code below causes an internal server error:
mw_instance = middleware(handler)
TypeError: object() takes no parameters
views.py
from django.http import HttpResponse
def my_view(request):
x = 1/0 # cause an exception
return HttpResponse("ok")
settings.py
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',
'myproject.middleware.ExceptionMiddleware',
]
middleware.py
from django.http import HttpResponse
class ExceptionMiddleware(object):
def process_exception(self, request, exception):
return HttpResponse("in exception")
I have seen these object() takes no parameters in django 1.10 and other questions talking about middleware versus middleware_classes, but I'm not sure how that applies to this case, or what I'd actually need to change to fix the issue.
Since you are using the new MIDDLEWARE settings, your Middleware class must accept a get_response argument: https://docs.djangoproject.com/en/1.10/topics/http/middleware/#writing-your-own-middleware
You could write your class like this:
from django.http import HttpResponse
class ExceptionMiddleware(object):
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
return self.get_response(request)
def process_exception(self, request, exception):
return HttpResponse("in exception")
You could also use the MiddlewareMixin to make your Middleware compatible with pre-1.10 and post-1.10 Django versions: https://docs.djangoproject.com/en/1.10/topics/http/middleware/#upgrading-pre-django-1-10-style-middleware
from django.http import HttpResponse
from django.utils.deprecation import MiddlewareMixin
class ExceptionMiddleware(MiddlewareMixin):
def process_exception(self, request, exception):
return HttpResponse("in exception")
in the newer version of Django, the middleware should be written like this
import datetime
from django.core.cache import cache
from django.conf import settings
from django.utils.deprecation import MiddlewareMixin
class ActiveUserMiddleware(MiddlewareMixin):
def process_request(self, request):
current_user = request.user
if request.user.is_authenticated:
now = datetime.datetime.now()
cache.set('seen_%s' % (current_user.username), now,
settings.USER_LASTSEEN_TIMEOUT)