Rest framework for aiohttp web server
Project description
aiohttp-rest-framework
Fully asynchronous rest framework for aiohttp web server, inspired by Django Rest Framework (DRF), powered by marshmallow and SQLAlchemy.
Currently supports only combination of postgres and sqlalchemy (ORM and core). MySQL support will be shipped on demand.
Installation
pip install aiohttp-rest-framework
Usage example
Consider we have the following SQLAlchemy ORM models:
models.py
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.orm import declarative_base
from app.utils import get_stringified_uuid
Base = declarative_base()
meta = Base.metadata
class User(Base):
__tablename__ = "users"
id = sa.Column(UUID, primary_key=True, default=get_stringified_uuid)
name = sa.Column(sa.Text)
email = sa.Column(sa.Text, nullable=False, unique=True)
phone = sa.Column(sa.Text)
company_id = sa.Column(sa.ForeignKey("companies.id"), nullable=True)
class Company(Base):
__tablename__ = "companies"
id = sa.Column(UUID, primary_key=True, default=get_stringified_uuid)
name = sa.Column(sa.Text, nullable=False)
SQLAlchemy Core tables are also supported.
import sqlalchemy as sa
from sqlalchemy.dialects.postgresql import UUID
from app.utils import get_stringified_uuid
meta = sa.MetaData()
User = sa.Table(
"users", meta,
sa.Column("id", UUID, primary_key=True, default=get_stringified_uuid),
sa.Column("name", sa.Text),
sa.Column("email", sa.Text, unique=True),
sa.Column("phone", sa.Text),
sa.Column("company_id", sa.ForeignKey("companies.id"), nullable=True),
)
Company = sa.Table(
"companies", meta,
sa.Column("id", UUID, primary_key=True, default=get_stringified_uuid),
sa.Column("name", sa.Text),
)
Now we can use very familiar to us from DRF serializer, built on top of marshmalow's Schema
:
serializers.py
from aiohttp_rest_framework import serializers
from app.models import User
class UserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = "__all__"
dump_only = ("id",)
Note: for more information about field declaration please refer to marshmallow
For SQLAlchemy ORM ModelSerializer
supports generic typing:
class UserSerializer(serializers.ModelSerializer[User]): # <- mention `User` here
class Meta:
model = User
fields = "__all__"
Now type hints will be available for serializers methods like create()
, update()
, etc.
And, finally, now we can use our serializer in class based views:
views.py
from aiohttp_rest_framework import views
from app.serializers import UserSerializer
class UsersListCreateView(views.ListCreateAPIView):
serializer_class = UserSerializer
class UsersRetrieveUpdateDestroyView(views.RetrieveUpdateDestroyAPIView):
serializer_class = UserSerializer
Our simple app would look like this:
main.py
from aiohttp import web
from aiohttp_rest_framework import setup_rest_framework, create_connection
from aiohttp_rest_framework.utils import create_tables
from app import views, config, models
async def db_cleanup_context(app_: web.Application) -> None:
app_["db"] = await create_connection(config.db_url)
# in case you need to create tables in the database
# for sqlalchemy this is the same as `meta.create_all()`, but asynchronous
await create_tables(models.meta, app_["db"])
yield
await app_["db"].dispose()
app = web.Application()
app.cleanup_ctx.append(db_cleanup_context)
app.router.add_view("/users", views.UsersListCreateView)
app.router.add_view("/users/{id}", views.UsersRetrieveUpdateDestroyView)
setup_rest_framework(app)
web.run_app(app)
Note: If you want to use other property than "db", in order to application work you have to specify
app_connection_property
in config, passing tosetup_rest_framework
.Example:
setup_rest_framework(app, {"app_connection_property": "custom_db_prop"})
Mention setup_rest_framework()
function, it is required to call it to configure framework to work with your app.
For available rest framework's config options refer to documentation.
For detailed aiohttp web app configuration please refer to their docs.
After starting the app, we can make a POST /users
request to create a new user.
curl -H "Content-Type: application/json"
-d '{
"name": "John Doe",
"email": "john@mail.com",
"phone": "+123456789"
}'
-X POST http://localhost:8080/users
And get the following HTTP 201 Response
:
{
"id": "aa392cc9-c734-44ff-9d7c-1602ecb4df2a",
"name": "John Doe",
"email": "john@mail.com",
"phone": "+123456789",
"company_id": null
}
Let's try to update user's company. Making PATCH /users/aa392cc9-c734-44ff-9d7c-1602ecb4df2a
request
curl -H "Content-Type: application/json"
-d '{"company_id": "0413de74-d9fb-494b-ba56-b56599261fb0"}'
-X PATCH http://localhost:8080/users/a392cc9-c734-44ff-9d7c-1602ecb4df2a
HTTP 200 Response
:
{
"id": "aa392cc9-c734-44ff-9d7c-1602ecb4df2a",
"name": "John Doe",
"email": "john@mail.com",
"phone": "+123456789",
"company_id": "0413de74-d9fb-494b-ba56-b56599261fb0"
}
For more examples and usages please refer to documentation.
Requirements
Python >= 3.6
Dependencies:
- aiohttp
- sqlalchemy
- marshmallow
If using PostgreSQL (currently being installed by default since it's the only database supported):
- asyncpg
- psycopg2
Documentation
setup_rest_framework(app, config)
Config is just a simple dict
object. Config can accept following parameters (everything is optional):
-
schema_type: str
- Specifies what combination of database and SQL toolkit to use. Currently supports only combination of SQLAlchemy and PostgreSQL.Default:
"sa"
-
app_connection_property: str
- The property name of the database connection in your aiohttp application.Default:
"db"
.
custom_db_prop = "db_conn"
async def db_cleanup_context(app_: web.Application) -> None:
app_[custom_db_prop] = await create_connection(config.db_url)
yield
await app_[custom_db_prop].dispose()
app = web.Application()
app.cleanup_ctx.append(db_cleanup_context)
setup_rest_framework(app, {"app_connection_property": custom_db_prop})
-
get_connection: Callable[[], Awaitable]
- An async callable that receive no arguments and returns database connection. You would only need it if you don't want to store your database connection in aiohttp application, then you have to provide it toaiohttp-rest-framework
so framework can work with a database.Default: uses
app[app_connection_property]
# somewhere in your code, function to get initialized db connection
from app.db import get_connection
# this is just to show that is has to be async
async def get_db_connection():
return await get_connection()
app = web.Application()
setup_rest_framework(app, {"get_connection": get_db_connection})
-
db_manager: BaseDBManager
- Specifies what database manager to use. You would need it if you want to use custom logic in database operations (class should be inherited fromBaseDBManager
imported fromaiohttp_rest_framework.db.base
). Usually you wouldn't need it because framework's built-inSAManager
(if you useschema_type = "sa"
, which is default) already handles all CRUD operations and also hasexecute()
method where you can pass custom sqlalchemy queries.Default: uses manager specific to the current
schema_type
.
A totally useless example just to show you how it can be used:
from aiohttp_rest_framework.db.sa import SAManager
class SAManagerWithPrintingQuery(SAManager):
async def execute(self, query, *args, **kwargs):
print(query)
return await super().execute(query, *args, **kwargs)
app = web.Application()
setup_rest_framework(app, {"db_manager": SAManagerWithPrintingQuery})
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
File details
Details for the file aiohttp_rest_framework-0.0.6.tar.gz
.
File metadata
- Download URL: aiohttp_rest_framework-0.0.6.tar.gz
- Upload date:
- Size: 19.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/54.0.0 requests-toolbelt/0.9.1 tqdm/4.58.0 CPython/3.9.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | eeaf882d78c92675bb132a45b57c6eba9953e1d59c11ab99a37f2c9fab533609 |
|
MD5 | f580c05dc217de670c6527523c4bc53b |
|
BLAKE2b-256 | abfbff34c0c33c8b25dc59c56fba6e8461eca93c161d7b15f92133750f6490ac |
File details
Details for the file aiohttp_rest_framework-0.0.6-py2.py3-none-any.whl
.
File metadata
- Download URL: aiohttp_rest_framework-0.0.6-py2.py3-none-any.whl
- Upload date:
- Size: 19.8 kB
- Tags: Python 2, Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/3.3.0 pkginfo/1.7.0 requests/2.25.1 setuptools/54.0.0 requests-toolbelt/0.9.1 tqdm/4.58.0 CPython/3.9.0
File hashes
Algorithm | Hash digest | |
---|---|---|
SHA256 | 4239ed293a5f441749391863fb2fbea628282566fdbc87dac2877defb90e2457 |
|
MD5 | 5a024177ae343fe52e9564b3c4bb7e1c |
|
BLAKE2b-256 | a2648616776bab3e7d790a0ed384bfa65025ee22d8d2e706d0c5c24716436217 |