28๐
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?)
10๐
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.
9๐
Check if you have django.contrib.messages
in INSTALLED_APPS
and django.contrib.messages.middleware.MessageMiddleware
in MIDDLEWARE_CLASSES
.
- Registered models do not show up in admin
- Converting a django ValuesQuerySet to a json object
- Accessing django project in LAN systems
- Django: WSGIRequest' object has no attribute 'user' on some pages?
5๐
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
- Django's {{ csrf_token }} is outputting the token value only, without the hidden input markup
- How to have a link in label of a form field
4๐
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
- Create a canonical "parent" product in Django Oscar programmatically
- Django database synchronization for an offline usage
- Django's get_current_language always returns "en"
- Sending a message to a single user using django-channels
- Registered models do not show up in admin
3๐
2018 update
In django 2.0+ name in settings was changed.
Right now use MIDDLEWARE
instead of MIDDLEWARE_CLASSES
name of list in settings!
- How can I test if my redis cache is working?
- How do I simulate connection errors and request timeouts in python unit tests
- How to emit SocketIO event on the serverside
1๐
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.
1๐
Probably you put a wrong WSGI_request
when usually called request
as a parameter to add_message()
method
- How does this Man-In-The-Middle attack work?
- Django: WSGIRequest' object has no attribute 'user' on some pages?
- Django template tag: How to send next_page in {url auth_logout}?
- Django render_to_string() ignores {% csrf_token %}
- How to customize django rest auth password reset email content/template
1๐
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: WSGIRequest' object has no attribute 'user' on some pages?
- Django render_to_string() ignores {% csrf_token %}
- Django template indentation guideline
- How can I test if my redis cache is working?
0๐
This is an implementation of Ramastโs answer, which only adds the approach I used for
overriding project settings in the test using a with
statment.
from django.contrib import messages
class TestClass(TestCase):
def setUp(self):
self.factory = RequestFactory()
<...>
def test_view_function(self):
with self.settings(
MESSAGE_STORAGE="django.contrib.messages.storage.cookie.CookieStorage"
): # configure the setting required for using the messages framework in this test.
data = {'form_field': 'form_data'}
request = self.factory.post('/any/path/will/do/', data)
request._messages = messages.storage.default_storage(request)
<...>
- Django render_to_string() ignores {% csrf_token %}
- How does django-nose differ from the default Django test-runner
- Accessing django project in LAN systems