aiohttp session¶
Session is a storage for saving temporary data like logged user info.
aiohttp_session library actually uses a middleware for session control.
Setup session support:
import aiohttp_session
async def init_app() -> web.Application:
app = web.Application()
app.add_routes(...)
aiohttp_session.setup(app, aiohttp_session.SimpleCookieStorage())
We use unsecured SimpleCookieStorage() for tutorial to save session data in browser
cookies.
More powerful alternatives are using EncryptedCookieStorage, NaClCookieStorage
or RedisStorage. If you want to use another storage system like database please
implement AbstractStorage interface and enjoy.
Session object¶
Session is available as session = await aiohttp_session.get_session(request) call.
The returned session object has dict-like interface:
session['NEW_KEY'] = value
The session is saved authomatically after finishing request handling.
Login and Logout¶
For login we use a simple HTML form:
@router.get("/login")
@aiohttp_jinja2.template("login.html")
async def login(request: web.Request) -> Dict[str, Any]:
return {}
@router.post("/login")
async def login_apply(request: web.Request) -> web.Response:
session = await aiohttp_session.get_session(request)
form = await request.post()
session["username"] = form["login"]
raise web.HTTPSeeOther(location="/")
view.html template:
{% block title %}
Login
{% endblock %}
{% block content %}
<h1>Login</h1>
<form action="/login" method="POST">
<input type="text" name="login">
<input type="submit">
</form>
{% endblock %}
Logout is even simpler:
@router.get("/logout")
async def logout(request: web.Request) -> web.Response:
session = await aiohttp_session.get_session(request)
session["username"] = None
raise web.HTTPSeeOther(location="/")
Getting username from post adding and modifying handlers¶
Let’s save logged in username as post’s editor:
@router.post("/{post}/edit")
@require_login
async def edit_post_apply(request: web.Request) -> web.Response:
post_id = request.match_info["post"]
session = await aiohttp_session.get_session(request)
editor = session["username"]
...
Note
Multiple get_session() calls returns the same session object if used for handling
the same HTTP request.
Last neat: use session data in rendering username by Jinja2 context processors:
async def username_ctx_processor(request: web.Request) -> Dict[str, Any]:
# Jinja2 context processor
session = await aiohttp_session.get_session(request)
username = session.get("username")
return {"username": username}
Rendering in template:
{% if username %}
<div>[{{ username }}] <a href="/logout">Logout</a></div>
{% else %}
<div>[Anonymous] <a href="/login">Login</a></div>
{% endif %}
Setup context processor:
async def init_app() -> web.Application:
app = web.Application()
...
aiohttp_jinja2.setup(
app,
loader=...,
context_processors=[username_ctx_processor],
)
Full example for server with sessions support¶
Example for HTML version of blogs server with images: Full server with sessions support