diff --git a/inertia/http.py b/inertia/http.py index 433c80c..9ed5b13 100644 --- a/inertia/http.py +++ b/inertia/http.py @@ -4,6 +4,7 @@ from json import dumps as json_encode from typing import Any, Callable +from django.contrib.messages import get_messages from django.core.exceptions import ImproperlyConfigured from django.http import HttpRequest, HttpResponse from django.template.loader import render_to_string @@ -112,7 +113,16 @@ def build_props(self) -> Any: if isinstance(_props[key], IgnoreOnFirstLoadProp): del _props[key] - return deep_transform_callables(_props) + _props = deep_transform_callables(_props) + + flash = [ + {"level": m.level_tag, "message": str(m)} + for m in get_messages(self.request) + ] + if flash: + _props["messages"] = flash + + return _props def build_deferred_props(self) -> dict[str, Any] | None: if self.request.is_a_partial_render(self.component): diff --git a/inertia/tests/test_messages.py b/inertia/tests/test_messages.py new file mode 100644 index 0000000..15a499f --- /dev/null +++ b/inertia/tests/test_messages.py @@ -0,0 +1,24 @@ +from inertia.test import InertiaTestCase + + +class FlashMessagesTestCase(InertiaTestCase): + def test_success_message_included_in_props(self): + self.inertia.get("/messages/") + self.assertIncludesProps({ + "messages": [{"level": "success", "message": "Profile saved!"}] + }) + + def test_no_messages_key_when_no_messages(self): + self.inertia.get("/no-messages/") + self.assertNotIn("messages", self.props()) + + def test_messages_consumed_after_render(self): + # First request — message should be present + self.inertia.get("/messages/") + self.assertIncludesProps({ + "messages": [{"level": "success", "message": "Profile saved!"}] + }) + + # Second request to a view with no messages — should not carry over + self.inertia.get("/no-messages/") + self.assertNotIn("messages", self.props()) diff --git a/inertia/tests/testapp/urls.py b/inertia/tests/testapp/urls.py index 7afcead..906752a 100644 --- a/inertia/tests/testapp/urls.py +++ b/inertia/tests/testapp/urls.py @@ -23,4 +23,6 @@ path("clear-history/", views.clear_history_test), path("clear-history-redirect/", views.clear_history_redirect_test), path("clear-history-type-error/", views.clear_history_type_error_test), + path("messages/", views.messages_test), + path("no-messages/", views.no_messages_test), ] diff --git a/inertia/tests/testapp/views.py b/inertia/tests/testapp/views.py index 26c9f1f..b097b54 100644 --- a/inertia/tests/testapp/views.py +++ b/inertia/tests/testapp/views.py @@ -1,3 +1,4 @@ +from django.contrib import messages from django.http.response import HttpResponse from django.shortcuts import redirect from django.utils.decorators import decorator_from_middleware @@ -152,3 +153,14 @@ def clear_history_redirect_test(request): def clear_history_type_error_test(request): request.session[INERTIA_SESSION_CLEAR_HISTORY] = "foo" return {} + + +@inertia("TestComponent") +def messages_test(request): + messages.success(request, "Profile saved!") + return {} + + +@inertia("TestComponent") +def no_messages_test(request): + return {}