Skip to content

maarten-dp/flastapi

main
Switch branches/tags

Name already in use

A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Table of contents

Introduction

Flastapi is a small flask plugin to enable a Fastapi-like interface to build API endpoints using pydantic.

Current features are:

  • path parameters using flask paths
  • query parameters
  • body parameters using pydantic
  • depends (including context dependencies)
  • dependency_overrides

Fastapi did a great job at integrating pydantic, as a marshaller for API endpoints, in an intuitive way. With this library I wanted to expose these capabilities in flast as well, for those who haven't found the ability to transition to newer techs (Or those who have a hard time dealing with change ;) )

Quickstart

from flask import Flask
from flastapi import FlastAPI, Router

app = Flask(__name__)
flastapi = FlastAPI(app)
router = Router("my_router")

@router.get("/index"):
def index():
    return {}

flastapi.add_router(router)

app.run()

API Overview

Path parameters

Both Flask and Fastapi offer similar path operations. As such, it didn't make sense to build a translation layer from a Fastapi notation to a Flask notation.

In short: We'll stick to flask path notations :)

Example endpoint

@router.get("/test/<int:some_param>")
def index(some_param: int):
    return {"some_param": some_param}

Example call

>>> client.get("/test/1")
{"some_param": 1}

Query parameters

Parameters annotated with builtin base types will automatically be flagged as query parameters. It's possible to gather query parameters in a pydantic model, check out the "Query dependency" section for more info.

Example endpoint

@router.get("/test")
def index(some_param: int):
    return {"some_param": some_param}

Example call

>>> client.get("/test?some_param=1")
{"some_param": 1}

Body parameters

Parameters annotated with pydantic models will automatically be flagged as json typed body parameters.

Example endpoint

class SomeParam(BaseModel):
    some_int: int


@router.post("/test")
def index(some_param: SomeParam):
    return some_param

Example call

>>> client.post("/test", json={"some_int": 1})
{"some_int": 1}

Multi body parameters

It's possible to annotate multiple pydantic models. If this is the case, the parameter names will be used as a lookup key in the json body.

Example endpoint

class SomeParam(BaseModel):
    some_int: int


class AnotherParam(BaseModel):
    some_str: str


@router.post("/test")
def index(some_param: SomeParam, another_param: AnotherParam):
    return [SomeParam, AnotherParam]

Example call

>>> client.post("/test", json={
    "some_param": {"some_int": 1},
    "another_param": {"some_str": "blah"}
})
[{"some_int": 1}, {"some_str": "blah"}]

Query dependency

If you'd like to group your query parameters in a pydantic model (or load them through another function), you can use a dependency.

from flastapi import Depends


class SomeParam(BaseModel):
    some_int: int


@router.get("/test")
def index(some_param: SomeParam = Depends(SomeParam)):
    return some_param

Example call

>>> client.get("/test?some_int=1")
{"some_int": 1}

Context dependency

A dependency also supports contexts, if you'd like a context to be started before handling the request, and closed after the request is handled.

from flastapi import Depends


def get_session():
    engine = create_engine("sqlite:////tmp/some.db")
    with Session(engine) as session:
        yield session


@router.get("/test")
def index(session: Session = Depends(get_session)):
    return {}

Testing dependencies

Overrides

You can override dependencies for your unit tests by replacing the wanted dependency with the one you'd like to run in your tests

Code

from flastapi import Depends


def get_session():
    engine = create_engine("sqlite:////tmp/some.db")
    with Session(engine) as session:
        yield session


@my_router.get("/test")
def index(session: Session = Depends(get_session)):
    return {}

Tests

from pytest import fixture
from flastapi import FlastAPI

from my_project import get_session, my_router


def get_test_session():
    engine = create_engine("sqlite:////tmp/another.db")
    with Session(engine) as session:
        yield session


@pytest.fixture
def app():
    app = Flask(__name__)
    flastapi = FlastAPI()
    flastapi.add_router(my_router)

    flastapi.dependency_overrides[get_session] = get_test_session

Using requests as test client

If you'd like to use requests as test client, check out Requests-flask-adapter

Roadmap

Stuff I'd still like to add

  • Response type
  • openAPI/Swagger/ReDoc support
  • I need to check out how this whole typing thing works in IDEs (Sorry, I'm a text editor kinda guy)

Requesting features

If you feel like stuff is missing, feel free to open an issue to request features. I'm but a poor programmer, fiddling for fun in his evenings, so I'll do my best to facilitate.

About

FastAPI-like interface plugin for Flask

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages