Change language in custom middleware - django

I would like to change language in my custom middleware. For some reason code below doesn't work.
class LanguageMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
print('set language to spanish...')
translation.activate("es")
request.LANGUAGE_CODE = "es"
response = self.get_response(request)
translation.deactivate()
return response
settings.py
LANGUAGES = (
("en", "English"),
("es", "Spanish"),
)
LOCALE_PATHS = (os.path.join(BASE_DIR, "locale"),)
USE_I18N = True
USE_L10N = True
LANGUAGE_CODE = "en"
if I change LANGUAGE_CODE is settings to "es" I get spanish API responses but I would like to be able to change it programmatically in my middleware.

This works for me:
def set_lang_middleware(get_response):
def middleware(request):
translation.activate("es")
response = get_response(request)
return response
return middleware
Do not forget to add your middleware in settings.MIDDLEWARE.

Related

how to set up Django translation on Heroku

help me, where am doing wrong
my settings.py
LANGUAGE_CODE = 'fr'
# LANGUAGE_COOKIE_NAME = 'LANGUAGES'
LOCALE_PATHS = (os.path.join(BASE_DIR, 'authentication/locale'),)
LANGUAGES = (
('fr', _('France')),
('en-us', _('English (US)')),
)
my views.py
def set_language(request):
language = request.POST.get('language', settings.LANGUAGE_CODE)
next_link = request.POST.get('next', "/")
user_language = 'fr'
translation.activate(user_language)
request.session[translation.LANGUAGE_SESSION_KEY] = "fr"
return redirect(next_link)
on local environment it works fine but not working on heroku, please help.

Django Middleware is not able to process view functions correctly

I am trying to do login/logout using Django Middleware. I have gone through few tutorials but all are posted with old versions. I am trying to hardcode the except function inside middleware instead of having in setting.py as follow:
middleware.py:
EXEMPT_FUNC = ['Accounts:login', 'Accounts:logout', 'Accounts:register']
class LoginRequiredMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
assert hasattr(request, 'user')
path = request.path_info.lstrip('/')
url_is_exempt = any(url.match(path) for url in EXEMPT_FUNC)
if path == reverse('Accounts:logout').lstrip('/'):
logout(request)
if request.user.is_authenticated() and url_is_exempt:
return redirect('User:home')
elif request.user.is_authenticated() or url_is_exempt:
return None
else:
return redirect('Accounts:login')
url.py:
app_name = 'Accounts'
urlpatterns = [
path('login', views.login_view, name='login'),
path('logout', views.logout_view, name='logout'),
path('register', views.register_view, name='register')
]
Above code is not working as intended, please help on what am I doing wrong.
Really appreciate your help.
Finally its working.
Here is what I changed.
middleware.py:
import re
from django.conf import settings
from django.urls import reverse
from django.shortcuts import redirect
from django.contrib.auth import logout
from Accounts import views
EXEMPT_PATH = ['login', 'logout', 'register']
class LoginRequiredMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
response = self.get_response(request)
return response
def process_view(self, request, view_func, view_args, view_kwargs):
assert hasattr(request, 'user')
path = request.path_info.lstrip('/')
exempt = False
if path in EXEMPT_PATH:
exempt = True
if path == 'logout':
logout(request)
if request.user.is_authenticated and exempt:
return redirect('User:home')
elif request.user.is_authenticated or exempt:
return None
else:
return redirect('Accounts:login')
With this approach I don't need to modify settings.py.
I hope this helps.

Django: Having 2 cookie sessions but app gets logged out when the admin app gets logged in (viceversa)

I want to have 2 sessions, one for my application (myapp.com) and one for the admin (myapp.com/admin). With this, I can have access to both in different tabs of my web client without logging in every time I want to use one of them. It is very irritating.
I have created a new session middleware to control that.
import time
from importlib import import_module
from django.conf import settings
from django.contrib.sessions.backends.base import UpdateError
from django.core.exceptions import SuspiciousOperation
from django.utils.cache import patch_vary_headers
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import http_date
class AdminCookieSessionMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
self.get_response = get_response
engine = import_module(settings.SESSION_ENGINE)
self.SessionStore = engine.SessionStore
def cookie_name(self, request):
parts = request.path.split('/')
if len(parts) > 1 and parts[1].startswith('admin'):
return settings.ADMIN_SESSION_COOKIE_NAME
return settings.SESSION_COOKIE_NAME
def cookie_path(self, request):
parts = request.path.split('/')
if len(parts) > 1 and parts[1].startswith('admin'):
return settings.ADMIN_SESSION_COOKIE_PATH
return settings.SESSION_COOKIE_PATH
def process_request(self, request):
session_key = request.COOKIES.get(self.cookie_name(request))
request.session = self.SessionStore(session_key)
def process_response(self, request, response):
"""
If request.session was modified, or if the configuration is to save the
session every time, save the changes and set a session cookie or delete
the session cookie if the session has been emptied.
"""
try:
accessed = request.session.accessed
modified = request.session.modified
empty = request.session.is_empty()
except AttributeError:
pass
else:
# First check if we need to delete this cookie.
# The session should be deleted only if the session is entirely empty
if settings.SESSION_COOKIE_NAME in request.COOKIES and empty:
response.delete_cookie(
settings.SESSION_COOKIE_NAME,
path=settings.SESSION_COOKIE_PATH,
domain=settings.SESSION_COOKIE_DOMAIN,
)
else:
if accessed:
patch_vary_headers(response, ('Cookie',))
if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
if request.session.get_expire_at_browser_close():
max_age = None
expires = None
else:
max_age = request.session.get_expiry_age()
expires_time = time.time() + max_age
expires = http_date(expires_time)
# Save the session data and refresh the client cookie.
# Skip session save for 500 responses, refs #3881.
if response.status_code != 500:
try:
request.session.save()
except UpdateError:
raise SuspiciousOperation(
"The request's session was deleted before the "
"request completed. The user may have logged "
"out in a concurrent request, for example."
)
response.set_cookie(
self.cookie_name(request),
request.session.session_key, max_age=max_age,
expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
path=settings.SESSION_COOKIE_PATH,
secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None,
)
return response
In my settings file:
SESSION_COOKIE_NAME='usersessionid'
ADMIN_SESSION_COOKIE_NAME='adminsessionid'
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',
'core.utils.middleware.AdminCookieSessionMiddleware'
]
However, I have still the problem that if logging in one of the apps, i got automatically logged out of the other.
I was tracing the sessionkey and sometimes it is the same for both coockies. is that ok? If not, what should the problem be?
OK, I could fix it, therefore I post the answer so I can help somebody trying to do that as well. I copy the code from the django SessionMiddleware and added a cookie_name function. Inside I created the logic that should apply for my needs.
Remember to replace settings.SESSION_COOKIE_NAME for cookie_name.
import time
from importlib import import_module
from django.conf import settings
from django.contrib.sessions.backends.base import UpdateError
from django.core.exceptions import SuspiciousOperation
from django.utils.cache import patch_vary_headers
from django.utils.deprecation import MiddlewareMixin
from django.utils.http import http_date
class MySessionMiddleware(MiddlewareMixin):
def __init__(self, get_response=None):
self.get_response = get_response
engine = import_module(settings.SESSION_ENGINE)
self.SessionStore = engine.SessionStore
def cookie_name(self, request):
parts = request.path.split('/')
if settings.DEBUG:
if len(parts)>1 and parts[1].startswith('admin'):
return settings.ADMIN_SESSION_COOKIE_NAME
else:
if len(parts)>2 and parts[2].startswith('admin'):
return settings.ADMIN_SESSION_COOKIE_NAME
return settings.SESSION_COOKIE_NAME
def process_request(self, request):
session_key = request.COOKIES.get(self.cookie_name(request))
request.session = self.SessionStore(session_key)
def process_response(self, request, response):
"""
If request.session was modified, or if the configuration is to save the
session every time, save the changes and set a session cookie or delete
the session cookie if the session has been emptied.
"""
try:
accessed = request.session.accessed
modified = request.session.modified
empty = request.session.is_empty()
except AttributeError:
pass
else:
# First check if we need to delete this cookie.
# The session should be deleted only if the session is entirely empty
cookie_name = self.cookie_name(request)
if cookie_name in request.COOKIES and empty:
response.delete_cookie(
cookie_name,
path=settings.SESSION_COOKIE_PATH,
domain=settings.SESSION_COOKIE_DOMAIN,
)
else:
if accessed:
patch_vary_headers(response, ('Cookie',))
if (modified or settings.SESSION_SAVE_EVERY_REQUEST) and not empty:
if request.session.get_expire_at_browser_close():
max_age = None
expires = None
else:
max_age = request.session.get_expiry_age()
expires_time = time.time() + max_age
expires = http_date(expires_time)
# Save the session data and refresh the client cookie.
# Skip session save for 500 responses, refs #3881.
if response.status_code != 500:
try:
request.session.save()
except UpdateError:
raise SuspiciousOperation(
"The request's session was deleted before the "
"request completed. The user may have logged "
"out in a concurrent request, for example."
)
response.set_cookie(
cookie_name,
request.session.session_key, max_age=max_age,
expires=expires, domain=settings.SESSION_COOKIE_DOMAIN,
path=settings.SESSION_COOKIE_PATH,
secure=settings.SESSION_COOKIE_SECURE or None,
httponly=settings.SESSION_COOKIE_HTTPONLY or None,
)
return response
And this is very important: in settings, in the MIDDELWARE list, you must add it but also remove the SessionMiddleware per default. Insert it in the same position where the normal SessionMiddleware was. The idea is to put it before 'django.contrib.auth.middleware.AuthenticationMiddleware', otherwise, you will get an error.
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
#'django.contrib.sessions.middleware.SessionMiddleware',
'core.utils.middleware.MySessionMiddleware',
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]

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'))

Clear Django cache for certain app or page

Is there any possibility to clear cache for certain app in django or for certain page?
I've tried to find it but in vain.
Thanks in advance.
Something like this might help you..
from django.core.cache import get_cache, DEFAULT_CACHE_ALIAS
from django.utils.cache import get_cache_key, _generate_cache_header_key, _generate_cache_key
from django.core.urlresolvers import reverse
from django.http import HttpRequest
from django.conf import settings
def expire_cache(path, args=[], cache_name=None, isview=True, lang_code=None, method='GET'):
if cache_name is None:
cache_name = DEFAULT_CACHE_ALIAS
cache = get_cache(cache_name)
key_prefix = settings.CACHES[cache_name].get('KEY_PREFIX', '')
request = HttpRequest()
if isview:
request.path = reverse(path, args=args)
else:
request.path = path
language_code = lang_code or getattr(settings, 'LANGUAGE_CODE')
if language_code:
request.LANGUAGE_CODE = language_code
header_key = _generate_cache_header_key(key_prefix, request)
if not header_key:
return False
headerlist = cache.get(header_key, None)
if headerlist is not None:
cache.set(header_key, None, 0)
page_key = _generate_cache_key(request, method, headerlist, key_prefix)
if not page_key:
return False
cache.set(page_key, None, 0)
return True
expire_cache('apps.yourapp.views.function')