aiohttp subapps: Create Modular Web Applications
Subapps in aiohttp allow you to modularize your application.
In this tutorial, you’ll learn how to create, configure, and use subapps in your aiohttp projects.
Create and Configure Subapps
To create a subapp, you’ll use the web.Application()
function.
Here’s how you can create and configure a simple subapp:
from aiohttp import web async def handle(request): return web.Response(text="Hello from subapp!") subapp = web.Application() subapp.add_routes([web.get('/', handle)]) main_app = web.Application() main_app.add_subapp('/subapp/', subapp) web.run_app(main_app)
Output:
======== Running on http://0.0.0.0:8080 ======== (Press CTRL+C to quit)
This code creates a subapp with a single route and adds it to the main application.
When you run this, the subapp will be accessible at http://localhost:8080/subapp/
.
Nested Subapps and Routing
You can nest subapps within other subapps. Here’s an example:
from aiohttp import web async def handle_admin(request): return web.Response(text="Admin panel") async def handle_users(request): return web.Response(text="User management") admin_app = web.Application() admin_app.add_routes([ web.get('/', handle_admin), web.get('/users', handle_users) ]) api_app = web.Application() api_app.add_subapp('/admin/', admin_app) main_app = web.Application() main_app.add_subapp('/api/', api_app) web.run_app(main_app)
This code creates a nested structure where the admin subapp is nested within the api subapp.
You can access the routes at http://localhost:8080/api/admin/
and http://localhost:8080/api/admin/users
.
Subapp-specific middleware
You can apply middleware specifically to a subapp:
from aiohttp import web @web.middleware async def subapp_middleware(request, handler): print("Subapp middleware: Before request") response = await handler(request) print("Subapp middleware: After request") return response async def handle(request): return web.Response(text="Hello from subapp!") subapp = web.Application(middlewares=[subapp_middleware]) subapp.add_routes([web.get('/', handle)]) main_app = web.Application() main_app.add_subapp('/subapp/', subapp) web.run_app(main_app)
Output:
Subapp middleware: Before request Subapp middleware: After request
This middleware will only be executed for requests to the subapp.
Interaction between Main App and Subapps
You can access the main app from within a subapp using the app['__main_app__']
attribute.
Here’s an example:
from aiohttp import web async def handle_main(request): return web.Response(text="Main app") async def handle_sub(request): main_app = request.app['__main_app__'] return web.Response(text=f"Subapp, main app routes: {list(main_app.router.routes())}") main_app = web.Application() main_app.add_routes([web.get('/', handle_main)]) subapp = web.Application() subapp.add_routes([web.get('/', handle_sub)]) main_app.add_subapp('/sub/', subapp) web.run_app(main_app)
This code allows the subapp to access information about the main app’s routes.
You can share resources by setting them on the main app and accessing them from subapps:
from aiohttp import web async def init_db(): return {"users": ["Alice", "Bob"]} async def handle_main(request): db = request.app['db'] return web.Response(text=f"Main app users: {db['users']}") async def handle_sub(request): db = request.app['__main_app__']['db'] return web.Response(text=f"Subapp users: {db['users']}") async def init_app(): app = web.Application() app['db'] = await init_db() app.add_routes([web.get('/', handle_main)]) subapp = web.Application() subapp.add_routes([web.get('/', handle_sub)]) app.add_subapp('/sub/', subapp) return app web.run_app(init_app())
This code initializes a database in the main app and shares it with the subapp.
You can use aiohttp_session to handle sessions across subapps:
from aiohttp import web from aiohttp_session import setup, get_session from aiohttp_session.cookie_storage import EncryptedCookieStorage async def handle_main(request): session = await get_session(request) session['visits'] = session.get('visits', 0) + 1 return web.Response(text=f"Main app visits: {session['visits']}") async def handle_sub(request): session = await get_session(request) return web.Response(text=f"Subapp visits: {session['visits']}") async def init_app(): app = web.Application() setup(app, EncryptedCookieStorage(b'Thirty two length bytes key.')) app.add_routes([web.get('/', handle_main)]) subapp = web.Application() subapp.add_routes([web.get('/', handle_sub)]) app.add_subapp('/sub/', subapp) return app web.run_app(init_app())
This code sets up session handling for both the main app and subapp.
You can create a shared configuration and pass it to subapps:
from aiohttp import web async def handle_main(request): config = request.app['config'] return web.Response(text=f"Main app config: {config}") async def handle_sub(request): config = request.app['__main_app__']['config'] return web.Response(text=f"Subapp config: {config}") async def init_app(): config = { 'debug': True, 'database_url': 'postgresql://user:pass@localhost/dbname' } app = web.Application() app['config'] = config app.add_routes([web.get('/', handle_main)]) subapp = web.Application() subapp.add_routes([web.get('/', handle_sub)]) app.add_subapp('/sub/', subapp) return app web.run_app(init_app())
This code creates a shared configuration that both the main app and subapp can access.
Pass data between subapps
You can use the main app as a central point to pass data between subapps:
from aiohttp import web async def handle_sub1(request): main_app = request.app['__main_app__'] main_app['shared_data'] = "Data from subapp1" return web.Response(text="Data set in subapp1") async def handle_sub2(request): main_app = request.app['__main_app__'] shared_data = main_app.get('shared_data', 'No data') return web.Response(text=f"Data in subapp2: {shared_data}") async def init_app(): app = web.Application() subapp1 = web.Application() subapp1.add_routes([web.get('/', handle_sub1)]) app.add_subapp('/sub1/', subapp1) subapp2 = web.Application() subapp2.add_routes([web.get('/', handle_sub2)]) app.add_subapp('/sub2/', subapp2) return app web.run_app(init_app())
This code shows how to pass data from one subapp to another using the main app as an intermediary.
Mokhtar is the founder of LikeGeeks.com. He is a seasoned technologist and accomplished author, with expertise in Linux system administration and Python development. Since 2010, Mokhtar has built an impressive career, transitioning from system administration to Python development in 2015. His work spans large corporations to freelance clients around the globe. Alongside his technical work, Mokhtar has authored some insightful books in his field. Known for his innovative solutions, meticulous attention to detail, and high-quality work, Mokhtar continually seeks new challenges within the dynamic field of technology.