All Projects → identixone → Fastapi_contrib

identixone / Fastapi_contrib

Licence: mit
Opinionated set of utilities on top of FastAPI

Programming Languages

python
139335 projects - #7 most used programming language

Labels

Projects that are alternatives of or similar to Fastapi contrib

Gonorth
GoNorth is a story and content planning tool for RPGs and other open world games.
Stars: ✭ 289 (-3.99%)
Mutual labels:  mongodb
Node Orm2
Object Relational Mapping
Stars: ✭ 3,063 (+917.61%)
Mutual labels:  mongodb
Hstardoc
My blogs write with markdown.
Stars: ✭ 297 (-1.33%)
Mutual labels:  mongodb
Pro Mern Stack
Code Listing for the book Pro MERN Stack
Stars: ✭ 290 (-3.65%)
Mutual labels:  mongodb
Vue Starbucks
Starbucks Front-End Project Developed by Vue.js
Stars: ✭ 291 (-3.32%)
Mutual labels:  mongodb
Hexagonal Architecture Acerola
An Hexagonal Architecture service template with DDD, CQRS, TDD and SOLID using .NET Core 2.0. All small features are testable and could be mocked. Adapters could be mocked or exchanged.
Stars: ✭ 293 (-2.66%)
Mutual labels:  mongodb
Blog
Front-end tech thoughts and share-ppt
Stars: ✭ 288 (-4.32%)
Mutual labels:  mongodb
Fullstack Apollo Express Mongodb Boilerplate
💥A sophisticated GraphQL with Apollo, Express and MongoDB boilerplate project.
Stars: ✭ 301 (+0%)
Mutual labels:  mongodb
Mongodb File Server
MongoDB File Server is a file server system based on MongoDB. 基于 MongoDB 的文件服务器。
Stars: ✭ 293 (-2.66%)
Mutual labels:  mongodb
Vue Fullstack
vue fullstack template
Stars: ✭ 297 (-1.33%)
Mutual labels:  mongodb
Mongorepository
Repository abstraction layer on top of Official MongoDB C# driver
Stars: ✭ 290 (-3.65%)
Mutual labels:  mongodb
Workarea
Workarea is an enterprise-grade Ruby on Rails commerce platform
Stars: ✭ 290 (-3.65%)
Mutual labels:  mongodb
Mongo Sync
Sync Remote and Local MongoDB Databases 🔥
Stars: ✭ 293 (-2.66%)
Mutual labels:  mongodb
Express Graphql Mongodb Boilerplate
A boilerplate for Node.js apps / GraphQL-API / Authentication from scratch - express, graphql - (graphql compose), mongodb (mongoose).
Stars: ✭ 288 (-4.32%)
Mutual labels:  mongodb
Yii2 Mongodb
Yii 2 MongoDB extension
Stars: ✭ 299 (-0.66%)
Mutual labels:  mongodb
Mern Social
A MERN stack based social media application [Full-Stack React Projects]
Stars: ✭ 288 (-4.32%)
Mutual labels:  mongodb
Ilruntime hotgames
基于ILRuntime的热更新能力实现的可以直接使用的框架,友情赠送C# WebService + WebSocketServer服务器端。
Stars: ✭ 293 (-2.66%)
Mutual labels:  mongodb
Securing Restful Apis With Jwt
How to secure a Nodejs RESTful CRUD API using JSON web tokens?
Stars: ✭ 301 (+0%)
Mutual labels:  mongodb
Hibernate Ogm
Hibernate OGM - Domain model persistence for NoSQL datastores
Stars: ✭ 299 (-0.66%)
Mutual labels:  mongodb
Jianshu
仿简书nx+nodejs+nestjs6+express+mongodb+angular8+爬虫
Stars: ✭ 296 (-1.66%)
Mutual labels:  mongodb

=============== FastAPI Contrib

.. image:: https://img.shields.io/pypi/v/fastapi_contrib.svg :target: https://pypi.python.org/pypi/fastapi_contrib

.. image:: https://img.shields.io/travis/identixone/fastapi_contrib.svg :target: https://travis-ci.org/identixone/fastapi_contrib

.. image:: https://readthedocs.org/projects/fastapi-contrib/badge/?version=latest :target: https://fastapi-contrib.readthedocs.io/en/latest/?badge=latest :alt: Documentation Status

.. image:: https://pyup.io/repos/github/identixone/fastapi_contrib/shield.svg :target: https://pyup.io/repos/github/identixone/fastapi_contrib/ :alt: Updates

Opinionated set of utilities on top of FastAPI

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
  • Opentracing middleware & setup utility with Jaeger tracer + root span available in every Request's state
  • StateRequestIDMiddleware: receives configurable header and saves it in request state

Roadmap

See GitHub Project Roadmap <https://github.com/identixone/fastapi_contrib/projects/2>_.

Installation

To install just Contrib (without mongodb, pytz, ujson):

.. code-block:: console

$ pip install fastapi_contrib

To install contrib with mongodb support:

.. code-block:: console

$ pip install fastapi_contrib[mongo]

To install contrib with ujson support:

.. code-block:: console

$ pip install fastapi_contrib[ujson]

To install contrib with pytz support:

.. code-block:: console

$ pip install fastapi_contrib[pytz]

To install contrib with opentracing & Jaeger tracer:

.. code-block:: console

$ pip install fastapi_contrib[jaegertracing]

To install everything:

.. code-block:: console

$ pip install fastapi_contrib[all]

Usage

To use Limit-Offset pagination:

.. code-block:: python

from fastapi import FastAPI
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
    )

Subclass this pagination to define custom default & maximum values for offset & limit:

.. code-block:: python

class CustomPagination(Pagination):
    default_offset = 90
    default_limit = 1
    max_offset = 100
    max_limit = 2000

To use State Request ID Middleware:

.. code-block:: python

from fastapi import FastAPI
from fastapi_contrib.common.middlewares import StateRequestIDMiddleware

app = FastAPI()

@app.on_event('startup')
async def startup():
    app.add_middleware(StateRequestIDMiddleware)

To use Authentication Middleware:

.. code-block:: python

from fastapi import FastAPI
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:

.. code-block:: python

from fastapi import FastAPI
from fastapi_contrib.permissions import BasePermission, PermissionsDependency

class TeapotUserAgentPermission(BasePermission):

    def has_required_permissions(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:

.. code-block:: python

from fastapi import FastAPI
from fastapi_contrib.exception_handlers import setup_exception_handlers

app = FastAPI()

@app.on_event('startup')
async def startup():
    setup_exception_handlers(app)

If you want to correctly handle scenario when request is an empty body (IMPORTANT: non-multipart):

.. code-block:: python

from fastapi import FastAPI
from fastapi_contrib.routes import ValidationErrorLoggingRoute

app = FastAPI()
app.router.route_class = ValidationErrorLoggingRoute

Or if you use multiple routes for handling different namespaces (IMPORTANT: non-multipart):

.. code-block:: python

from fastapi import APIRouter, FastAPI
from fastapi_contrib.routes import ValidationErrorLoggingRoute

app = FastAPI()

my_router = APIRouter(route_class=ValidationErrorLoggingRoute)

To correctly show slashes in fields with URLs + ascii locking:

.. code-block:: python

from fastapi import FastAPI
from fastapi_contrib.common.responses import UJSONResponse

app = FastAPI()

@app.get("/", response_class=UJSONResponse)
async def root():
    return {"a": "b"}

Or specify it as default response class for the whole app (FastAPI >= 0.39.0):

.. code-block:: python

from fastapi import FastAPI
from fastapi_contrib.common.responses import UJSONResponse

app = FastAPI(default_response_class=UJSONResponse)

To setup Jaeger tracer and enable Middleware that captures every request in opentracing span:

.. code-block:: python

from fastapi import FastAPI
from fastapi_contrib.tracing.middlewares import OpentracingMiddleware
from fastapi_contrib.tracing.utils import setup_opentracing

app = FastAPI()

@app.on_event('startup')
async def startup():
    setup_opentracing(app)
    app.add_middleware(OpentracingMiddleware)

To setup mongodb connection at startup and never worry about it again:

.. code-block:: python

from fastapi import FastAPI
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:

.. code-block:: python

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:

.. code-block:: python

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:

.. code-block:: python

from fastapi import FastAPI
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:

.. code-block:: json

{"read_only1": "a", "write_only2": 123, "field1": "b"}

Should return following response:

.. code-block:: json

{"id": 1, "field1": "b", "read_only1": "const"}

Auto-creation of MongoDB indexes

Suppose we have this directory structure:

.. code-block:: console

-- project_root/
     -- apps/
          -- app1/
               -- models.py (with MongoDBModel inside with indices declared)
          -- app2/
               -- models.py (with MongoDBModel inside with indices declared)

Based on this, your name of the folder with all the apps would be "apps". This is the default name for fastapi_contrib package to pick up your structure automatically. You can change that by setting ENV variable CONTRIB_APPS_FOLDER_NAME (by the way, all the setting of this package are overridable via ENV vars with CONTRIB_ prefix before them).

You also need to tell fastapi_contrib which apps to look into for your models. This is controlled by CONTRIB_APPS ENV variable, which is list of str names of the apps with models. In the example above, this would be CONTRIB_APPS=["app1","app2"].

Just use create_indexes function after setting up mongodb:

.. code-block:: python

from fastapi import FastAPI
from fastapi_contrib.db.utils import setup_mongodb, create_indexes

app = FastAPI()

@app.on_event("startup")
async def startup():
    setup_mongodb(app)
    await create_indexes()

This will scan all the specified CONTRIB_APPS in the CONTRIB_APPS_FOLDER_NAME for models, that are subclassed from either MongoDBModel or MongoDBTimeStampedModel and create indices for any of them that has Meta class with indexes attribute:

models.py:

.. code-block:: python

import pymongo
from fastapi_contrib.db.models import MongoDBTimeStampedModel


class MyModel(MongoDBTimeStampedModel):

    class Meta:
        collection = "mymodel"
        indexes = [
            pymongo.IndexModel(...),
            pymongo.IndexModel(...),
        ]

This would not create duplicate indices because it relies on pymongo and motor to do all the job.

Credits

This package was created with Cookiecutter_ and the audreyr/cookiecutter-pypackage_ project template.

.. _Cookiecutter: https://github.com/audreyr/cookiecutter .. _audreyr/cookiecutter-pypackage: https://github.com/audreyr/cookiecutter-pypackage

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].