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