Skip to content

Messages#

One-shot flash messages across a redirect -- "Saved!", "Invalid credentials", that kind of thing.

Why this works differently from Django#

Django's messages framework rides on its generic session storage. Hayavega's sessions are auth-specific -- server-side, keyed by an opaque token issued only at login -- so there's no equivalent session table to store messages in for an anonymous visitor. Messages instead live in a small JSON-encoded hayavega_messages cookie: queued on an outgoing Response, read and cleared on the next request's Response. Keep messages short -- cookies have a practical ~4KB limit, so this is a notification channel, not a general data-passing one.

Response is a frozen dataclass, so neither function below mutates one -- both return a (new) Response instead.

Queuing a message#

from hayavega.messages import SUCCESS, add_message
from hayavega.response import Response


def save_post(request):
    ...
    response = Response("", status=303, headers=(("Location", "/posts"),))
    return add_message(response, SUCCESS, "Post saved.")

Calling add_message more than once on the same response chain accumulates every message into the one cookie:

response = add_message(response, SUCCESS, "Post saved.")
response = add_message(response, "info", "You have 2 drafts pending review.")

Reading and clearing messages#

from hayavega.messages import consume_messages


def posts_list(request):
    draft = Response(render_template("posts.html", {"posts": posts}))
    messages, response = consume_messages(request, draft)
    return response

consume_messages(request, draft_response) returns (messages, response) -- the queued Message objects, and a copy of draft_response with the cookie cleared so the same messages don't show again on the next request. If there was nothing queued, it returns ([], draft_response) unchanged -- no cookie-clearing header added when there's nothing to clear.

Levels#

hayavega.messages defines DEBUG, INFO, SUCCESS, WARNING, ERROR as plain string constants -- the same level names Django's messages use, for familiarity. add_message accepts any string, so your own levels work too; Message.level is just whatever you passed.