Opinionated set of utilities on top of FastAPI
Project description
FastAPI Contrib
Opinionated set of utilities on top of FastAPI
Free software: MIT license
Documentation: https://fastapi-contrib.readthedocs.io.
Features
Auth Backend & Middleware (User or None in every request object)
Permissions: reusable class permissions, specify multiple as FastAPI Dependency
ModelSerializers: serialize (pydantic) incoming request, connect data with DB model and save
UJSONResponse: correctly show slashes in fields with URLs
Limit-Offset Pagination: use it as FastAPI Dependency (works only with ModelSerializers for now)
MongoDB integration: Use models as if it was Django (based on pydantic models)
MongoDB indices verification on startup of the app
Custom Exceptions and Custom Exception Handlers
StateRequestIDMiddleware: receives configurable header and saves it in request state
Usage
To use Limit-Offset pagination:
from fastapi_contrib.pagination import Pagination
from fastapi_contrib.serializers.common import ModelSerializer
from yourapp.models import SomeModel
app = FastAPI()
class SomeSerializer(ModelSerializer):
class Meta:
model = SomeModel
@app.get("/")
async def list(pagination: Pagination = Depends()):
filter_kwargs = {}
return await pagination.paginate(
serializer_class=SomeSerializer, **filter_kwargs
)
To use State Request ID Middleware:
from fastapi_contrib.common.middlewares import StateRequestIDMiddleware
app = FastAPI()
@app.on_event('startup')
async def startup():
app.add_middleware(StateRequestIDMiddleware)
To use Authentication Middleware:
from fastapi_contrib.auth.backends import AuthBackend
from fastapi_contrib.auth.middlewares import AuthenticationMiddleware
app = FastAPI()
@app.on_event('startup')
async def startup():
app.add_middleware(AuthenticationMiddleware, backend=AuthBackend())
Define & use custom permissions based on FastAPI Dependency framework:
from fastapi_contrib.permissions import BasePermission, PermissionsDependency
class TeapotUserAgentPermission(BasePermission):
def has_required_permisions(self, request: Request) -> bool:
return request.headers.get('User-Agent') == "Teapot v1.0"
app = FastAPI()
@app.get(
"/teapot/",
dependencies=[Depends(
PermissionsDependency([TeapotUserAgentPermission]))]
)
async def teapot() -> dict:
return {"teapot": True}
Setup uniform exception-handling:
from fastapi_contrib.exception_handlers import setup_exception_handlers
app = FastAPI()
@app.on_event('startup')
async def startup():
setup_exception_handlers(app)
To correctly show slashes in fields with URLs + ascii locking:
from fastapi_contrib.common.responses import UJSONResponse
app = FastAPI()
@app.get("/", response_class=UJSONResponse)
async def root():
return {"a": "b"}
To setup mongodb connection at startup and never worry about it again:
from fastapi_contrib.db.utils import setup_mongodb
app = FastAPI()
@app.on_event('startup')
async def startup():
setup_mongodb(app)
Use models to map data to MongoDB:
from fastapi_contrib.db.models import MongoDBModel
class MyModel(MongoDBModel):
additional_field1: str
optional_field2: int = 42
class Meta:
collection = "mymodel_collection"
mymodel = MyModel(additional_field1="value")
mymodel.save()
assert mymodel.additional_field1 == "value"
assert mymodel.optional_field2 == 42
assert isinstance(mymodel.id, int)
Or use TimeStamped model with creation datetime:
from fastapi_contrib.db.models import MongoDBTimeStampedModel
class MyTimeStampedModel(MongoDBTimeStampedModel):
class Meta:
collection = "timestamped_collection"
mymodel = MyTimeStampedModel()
mymodel.save()
assert isinstance(mymodel.id, int)
assert isinstance(mymodel.created, datetime)
Use serializers and their response models to correctly show Schemas and convert from JSON/dict to models and back:
from fastapi_contrib.db.models import MongoDBModel
from fastapi_contrib.serializers import openapi
from fastapi_contrib.serializers.common import Serializer
from yourapp.models import SomeModel
app = FastAPI()
class SomeModel(MongoDBModel):
field1: str
@openapi.patch
class SomeSerializer(Serializer):
read_only1: str = "const"
write_only2: int
not_visible: str = "42"
class Meta:
model = SomeModel
exclude = {"not_visible"}
write_only_fields = {"write_only2"}
read_only_fields = {"read_only1"}
@app.get("/", response_model=SomeSerializer.response_model)
async def root(serializer: SomeSerializer):
model_instance = await serializer.save()
return model_instance.dict()
POST-ing to this route following JSON:
{"read_only1": "a", "write_only2": 123, "field1": "b"}
Should return following response:
{"id": 1, "field1": "b", "read_only1": "const"}
Credits
This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.
History
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
Hashes for fastapi_contrib-0.1.1-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | a7d355d3ef9838b3ea6ebb6bb25049580d7a17c7c0908957cf34eba1b27e834f |
|
MD5 | 5e1c3e18e370843df8b90166f0c43e46 |
|
BLAKE2b-256 | 8ad403dddc774ee0b24e10e0f1751b31f06243b33ab63c9e4d79a277ae47d266 |