Flash Messages
Flash messages give users temporary, one-time feedback after they perform an action, such as "Post created successfully" or "Invalid file type". A message survives a single HTTP redirect, and the admin discards it after it's displayed.
flash() queues a message on the current request. The admin renders the message on the next page the user sees, then clears the queue. This pattern comes from Flask-Admin.
from starlette.requests import Request
from starlette_admin import BaseModelView
from starlette_admin.flash import flash
class PostView(BaseModelView):
async def before_create(self, request: Request, data: dict) -> None:
if not data.get("title", "").strip():
# Queue the message for the next page load
flash(request, "Title cannot be blank.", category="error")
raise ValueError("Title cannot be blank.")
Message categories
Every flash message needs a category. The category sets the color of the banner in the default theme, so users can gauge severity at a glance.
from starlette_admin.flash import flash
flash(request, "Report generated.", category="success")
flash(request, "3 rows were skipped.", category="info")
flash(request, "This action can't be undone.", category="warning")
flash(request, "Upload failed: file too large.", category="error")
The category argument defaults to "info". It must be exactly one of success, info, warning, or error. Any other value raises a ValueError.
Built-in CRUD messages
You don't need to call flash() for standard CRUD operations. The admin flashes a success message automatically when these actions finish:
| Action | Default message |
|---|---|
| Create | The item "<repr>" was added successfully. |
| Edit | The item "<repr>" was changed successfully. |
| Delete (single) | The item "<repr>" was successfully deleted. |
| Delete (bulk) | %(count)d items were successfully deleted. |
What <repr> resolves to
The automatic messages use the row representation that view.repr() defines, not the model's class name. For example, creating a post flashes "The item 'My First Post' was added successfully" rather than a generic "Post was added successfully".
Using flash messages in custom actions
Handlers for custom actions (@action and @row_action) return None by default. To give the user feedback, call flash() before the handler returns.
from starlette.requests import Request
from starlette_admin import BaseModelView, action, flash
class PostView(BaseModelView):
@action(
name="publish",
text="Publish",
confirmation="Publish the selected posts?",
)
async def publish_action(self, request: Request, pks: list) -> None:
for pk in pks:
obj = await self.find_by_pk(request, pk)
obj.published = True
await self.edit(request, pk, {"published": True})
# Notify the user that the custom action succeeded
flash(request, f"{len(pks)} post(s) published.", category="success")
- If you omit
flash(): The action still runs, but the user gets no visual confirmation after the page redirects. - If the action fails: When your custom action raises
ActionFailed, the admin intercepts the exception and displays the exception string as an error banner. Don't callflash()in anActionFailedbranch, because the request doesn't redirect.
Rendering messages in custom templates
The admin's base template pops and renders flash messages for you. You only need to retrieve them yourself when you build a fully custom view.
from starlette_admin.flash import get_flashed_messages
messages = get_flashed_messages(request)
# Returns: [{"message": "The item \"My First Post\" was added successfully.", "category": "success"}]
Reading the flash queue is destructive. The first call to get_flashed_messages(request) pops and clears the queue. Later calls during the same request return an empty list, [].
Keep messages short
Flash messages live in a signed, httponly cookie named admin_flash, not in the server session. Browsers limit cookie size to roughly 4 KB, so use flash messages only for brief feedback. Avoid long strings and large data payloads. The cookie-based approach also means flash messages work without SessionMiddleware.
See examples/09-actions for a runnable app that calls
flash()from hooks and custom actions.