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 ;) )
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()
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 :)
@router.get("/test/<int:some_param>")
def index(some_param: int):
return {"some_param": some_param}
>>> client.get("/test/1")
{"some_param": 1}
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.
@router.get("/test")
def index(some_param: int):
return {"some_param": some_param}
>>> client.get("/test?some_param=1")
{"some_param": 1}
Parameters annotated with pydantic models will automatically be flagged as json typed body parameters.
class SomeParam(BaseModel):
some_int: int
@router.post("/test")
def index(some_param: SomeParam):
return some_param
>>> client.post("/test", json={"some_int": 1})
{"some_int": 1}
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.
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]
>>> client.post("/test", json={
"some_param": {"some_int": 1},
"another_param": {"some_str": "blah"}
})
[{"some_int": 1}, {"some_str": "blah"}]
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
>>> client.get("/test?some_int=1")
{"some_int": 1}
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 {}
You can override dependencies for your unit tests by replacing the wanted dependency with the one you'd like to run in your tests
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 {}
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
If you'd like to use requests as test client, check out Requests-flask-adapter
- 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)
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.