Concatenate Django Settings "MIDDLEWARE_CLASSES" - django

I want to import the django default settings, using from django.conf import global_settings, and then add MIDDLEWARE_CLASSES to it. I like to do this with my settings so that I know what I have added and what is default. So my settings file would look like this:
from django.conf import global_settings
...
global_settings.MIDDLEWARE_CLASSES += (
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
This strategy works for other settings, such as TEMPLATE_CONTEXT_PROCESSORS, but when I try it, it isn't working. I added print global_settings.MIDDLEWARE_CLASSES after adding the Debug Toolbar Middlware and this was my output when using runserver
('django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware')
('django.middleware.common.CommonMiddleware', 'django.contrib.sessions.middleware.SessionMiddleware', 'django.middleware.csrf.CsrfViewMiddleware', 'django.contrib.auth.middleware.AuthenticationMiddleware', 'django.contrib.messages.middleware.MessageMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware', 'debug_toolbar.middleware.DebugToolbarMiddleware')
Validating models...
0 errors found
Django version 1.3.1, using settings 'canada.settings'
Development server is running at http://127.0.0.1:8000/
Quit the server with CONTROL-C.
If you scroll over you can see that it runs through the settings twice. The second time it adds the setting again. How can I prevent this? To I have to just hard code my MIDDLEWARE_CLASSES in the settings? Also is there a good reason not to import the default django settings?

I don't think it's recommended that you make changes directly to global_settings variable. The Django core does a lot of screwing around with it as it merges in all the stuff you define in settings.py, so it may be that your changes are getting overwritten.
If you really want to derive your variables from global_settings directly, I'd make a local copy, then modify that. Example:
GLOBAL_MIDDLEWARE_CLASSES = global_settings.MIDDLEWARE_CLASSES
LOCAL_MIDDLEWARE_CLASSES = ('debug_toolbar.middleware.DebugToolbarMiddleware',)
MIDDLEWARE_CLASSES = GLOBAL_MIDDLEWARE_CLASSES + LOCAL_MIDDLEWARE_CLASSES
Django should then pick up that you've defined a new version of MIDDLEWARE_CLASSES, and insert it into global_middleware using the proper process.
This being said, I personally would prefer to have all the middleware classes there for me to see and re-arrange if needed. By using the method you've chosen, you don't know what could change between Django revisions!

Related

Django Debug Toolbar shows at root URL, but not in app URL

I have a new project and I'm trying to set up Django Debug Toolbar. First I tried the quick setup, which only involves adding 'debug_toolbar' to my list of installed apps. With this, the debug toolbar showed up when I went to my root URL, but it did not work for my app urls/views. I should not that presently, my root URL is not linked to a view, so it was showing a django error page.
Since the quick start didn't work, I went with the explicit setup. I updated my settings file:
DEBUG_TOOLBAR_PATCH_SETTINGS = False
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',
'debug_toolbar.middleware.DebugToolbarMiddleware',
)
And updated my project-level urls.py:
if settings.DEBUG: # make sure the toolbar is above ?CKeditor and FeinCMS
import debug_toolbar
urlpatterns += patterns('',
url(r'^__debug__/', include(debug_toolbar.urls)),
)
But now it doesn't show up anywhere.
In my app view, I've added a {% debug %} to the template. The template debug output does seem to indicate that the debug toolbar middleware has been loaded:
'debug_toolbar': <module 'debug_toolbar' from '/home/joseph/.virtualenvs/myproject/local/lib/python2.7/site-packages/debug_toolbar/__init__.pyc'>,
'debug_toolbar.collections': None,
'debug_toolbar.compat': <module 'debug_toolbar.compat' from '/home/joseph/.virtualenvs/myproject/local/lib/python2.7/site-packages/debug_toolbar/compat.pyc'>,
'debug_toolbar.django': None,
'debug_toolbar.importlib': None,
'debug_toolbar.middleware': <module 'debug_toolbar.middleware' from '/home/joseph/.virtualenvs/myproject/local/lib/python2.7/site-packages/debug_toolbar/middleware.pyc'>,
I'm not sure why this isn't working. My django version is 1.8 and my debug toolbar version is 1.3.2.
My solution to this problem was to add <body></body> tags to the template.
I got it from the "Tips" section on django-debug-toolbar site.
The Debug Toolbar will only display when DEBUG = True in your project’s settings. It will also only display if the mimetype of the response is either text/html or application/xhtml+xml and contains a closing </body> tag.
Source: django-debug-toolbar.readthedocs.io/en/stable/tips.html
If the toolbar works on index page (or any other) but not on another, missing body tags are probably the reason.

How can I check my website is currently protect against csrf?

I am working on a dJango web and follow the tutorial to protect it against CSRF, I did something and not sure is it write now install or not, how can I see or check it?
From the docs, to enable CSRF protection for your views, follow these steps:
Add the middleware 'django.middleware.csrf.CsrfViewMiddleware' to your list of middleware classes, MIDDLEWARE_CLASSES in your settings.py. (It should come before any view middleware that assume that CSRF attacks have been dealt with.)
In any template that uses a POST form, use the csrf_token tag inside the element if the form is for an internal URL, e.g.:
<form action="." method="post">{% csrf_token %}
In the corresponding view functions, ensure that the 'django.core.context_processors.csrf' context processor is being used.
Following these steps will check that CSRF tokens are included properly.
By default, a ‘403 Forbidden’ response is sent to the user if an incoming request fails the checks performed by CsrfViewMiddleware. This should usually only be seen when there is a genuine Cross Site Request Forgery, or when, due to a programming error, the CSRF token has not been included with a POST form.
See the Docs for more info.
Check the MIDDLEWARE_CLASSES tuple in settings.py contains this
'django.middleware.csrf.CsrfViewMiddleware',
If this is there in the tuple , then csrf is installed.
Some like this:
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
# Uncomment the next line for simple clickjacking protection:
# 'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware

I am new to Django.
I am trying to run an app and I need to add a new user to admin. The server is running. When I enter the info fir the new user and hit "save" I get the error below. I am using django-trunk.
MessageFailure at /admin/auth/user/add/
You cannot add messages without installing
django.contrib.messages.middleware.MessageMiddleware
Request Method: POST
Request URL: http://localhost:8000/admin/auth/user/add/
Django Version: 1.6.dev20130403090717
Exception Type: MessageFailure
Exception Value: You cannot add messages without installing django.contrib.messages.middleware.MessageMiddleware
Any ideas of what might be happening?
For me the problem was specific to unit testing. It turns out that some middleware won't work in some kinds of unit tests, more info here:
https://code.djangoproject.com/ticket/17971
and here:
Why don't my Django unittests know that MessageMiddleware is installed?
My solution was to just mock out the messages framework for those tests, there may be better solutions (the django test client?)
Check if you have django.contrib.messages in INSTALLED_APPS and django.contrib.messages.middleware.MessageMiddleware in MIDDLEWARE_CLASSES.
If you are running normal django code, you should add
django.contrib.messages.middleware.MessageMiddleware to your middlewares as others have suggested
If you are running a test case and using request factory then as #hwjp answered above, it's a bug (that won't be fixed). The request factory doesn't call the middlewares and developers don't intend to change this behaviour.
There is however a simple solution.
in your test settings file (i.e settings/test.py) add the following line
MESSAGE_STORAGE = 'django.contrib.messages.storage.cookie.CookieStorage'
in your test code you can write code like this
request = RequestFactory().get("/")
# Add support django messaging framework
request._messages = messages.storage.default_storage(request)
and that's it. Passing this request object to any code that uses django messages will work without a problem.
Check if it is
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
instead of
MIDDLEWARE = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
Tuple name should be MIDDLEWARE_CLASSES
MIDDLEWARE_CLASSES depreciated https://docs.djangoproject.com/en/2.1/releases/1.10/#id3
2018 update
In django 2.0+ name in settings was changed.
Right now use MIDDLEWARE instead of MIDDLEWARE_CLASSES name of list in settings!
If the request is needed in tests, it can be mocked as suggested by #Ramast.
I found the solution mentioned in the bug ticket (closed, won't fix) to be helpful.
from django.contrib.messages.storage.fallback import FallbackStorage
from django.test import RequestFactory
def dummy_request():
"""Dummy request for testing purposes with message support."""
request = RequestFactory().get('/')
# Add support django messaging framework
setattr(request, 'session', 'session')
setattr(request, '_messages', FallbackStorage(request))
return request
Probably you put a wrong WSGI_request when usually called request as a parameter to add_message() method
I met the same error.
You have to notice the order of middleware in MIDDLEWARE_CLASSES.
Insert the corresponding middleware in the final.Like this,
MIDDLEWARE_CLASSES = (
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
)
Note the order arrangement.
If your issue is simulating these middlewares during unit testing, you can spoof this by writing a couple of little helpers:
def add_session_to_request(request: HttpRequest) -> HttpRequest:
"""Adds session support to a RequestFactory generated request."""
middleware = SessionMiddleware(get_response=lambda request: None)
middleware.process_request(request)
request.session.save()
return request
def add_messages_to_request(request: HttpRequest) -> HttpRequest:
"""Adds message/alert support to a RequestFactory generated request."""
request._messages = FallbackStorage(request)
return request
You can then call these in your test function at the point your request needs to have the middleware bound and just pass in the request you're using, which should keep your tests happy. :)
# To suppress the errors raised when triggering .messages through APIRequestFactory(),
# we need to bind both a session and messages storage on the fly
add_session_to_request(replacement_request)
add_messages_to_request(replacement_request)

Django-nonrel with Google App Engine: Missing AutoloadMiddelware class?

I just deployed a website using Google App Engine that I built using Django. However, whenever I try to view my site live, I get a 500 error, and when I go into the App Engine dashboard and check the logs, I see the error:
"ImproperlyConfigured: Middleware module "autoload.middleware" does
not define a "AutoloadMiddelware" class"
But this doesn't quite make sense as I checked the autoload folder in my project and inside, there is a middeware.py file that indeed defines an AutoloadMiddleware class as follows:
from django.utils.importlib import import_module
from django.conf import settings
# load all models.py to ensure signal handling installation or index loading
# of some apps
for app in settings.INSTALLED_APPS:
try:
import_module('%s.models' % (app))
except ImportError:
pass
class AutoloadMiddleware(object):
"""Empty because the import above already does everything for us"""
pass
Is there something wrong with the import, perhaps? Is it possible my deployment didn't upload the necessary django modules in addition to those in my project folder?
Make sure you add it to your settings.py
MIDDLEWARE_CLASSES = (
# This loads the index definitions, so it has to come first
'autoload.middleware.AutoloadMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
)

Django--URL Caching Failing for Class Based Views

I've built a RESTful API on top of the Django Rest Framework. The URL conf for the API is composed of class based views.
I would like to cache these views, however, the following is failing. Any thoughts on why that might be and how I could change it?
from django.views.decorators.cache import cache_page
urlpatterns = patterns('',
url(r'^dounces/?$', cache_page(60*60)(DounceListView.as_view(resource=DounceResource)), name='dounces_api'),
I have the following middleware installed.
'django.middleware.gzip.GZipMiddleware',
'django.middleware.common.CommonMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.transaction.TransactionMiddleware',
'django.contrib.redirects.middleware.RedirectFallbackMiddleware',
AND for local testing, i'm using the default caching backend:
'BACKEND': 'django.core.cache.backends.locmem.LocMemCache',
change your urlconf to
urlpatterns = patterns('',
url(r'^dounces/?$', cache_page(60*60)(DounceListView.as_view(resource=DounceResource)), name='dounces_api'),
)
also see https://docs.djangoproject.com/en/1.7/topics/cache/#specifying-per-view-cache-in-the-urlconf
The other answer is out of date. The correct way is detailed here:
https://docs.djangoproject.com/en/1.6/topics/cache/#specifying-per-view-cache-in-the-urlconf
It has to now be done this way:
urlpatterns = patterns('',
url(r'^dounces/?$', cache_page(60*60)(DounceListView.as_view(resource=DounceResource)), name='dounces_api'),
)
I dont see any "django.middleware.cache.UpdateCacheMiddleware" and "django.middleware.cache.FetchFromCacheMiddleware". I dont think it can cache properly without it.
https://docs.djangoproject.com/en/2.2/topics/cache/