Databases¶
config.yml¶
If we use a database in our service we declare the connection info in the
config.yml
of the service like the following:
app/config.yml
¶...
external_resources:
services: null
databases:
userdb:
dsn: 'postgresql://postgres:1234@localhost:5434/userdb'
databasetype: 'postgres'
min_size: 5
max_size: 20
other: null
...
For each database we want to use in our service, we define a new item inside
databases
.
The key will be the name of our database.
The connection itself is defined as dsn
.
The databasetype defines the type of the database we are using.
This setting is for future releases of fastapi-serviceutils.
Currently we only support postgres
and this setting has no effect.
min_size
and max_size
define the minimum and maximum amount of
connections to open to the database.
app/endpoints/v1/dbs.py¶
Inside the module dbs.py
we define our datatables like the following:
app/endpoints/v1/dbs.py
¶from sqlalchemy import Boolean
from sqlalchemy import Column
from sqlalchemy import insert
from sqlalchemy import Integer
from sqlalchemy import String
from sqlalchemy.ext.declarative import declarative_base
Base = declarative_base()
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True, index=True)
email = Column(String, unique=True, index=True)
password = Column(String)
app/endpoints/v1/models.py¶
As for each endpoint we declare the input- and output-models we are using in our new endpoints like the following:
app/endpoints/v1/models.py
¶from pydantic import BaseModel
class InsertUser(BaseModel):
email: str
password: str
class Inserted(BaseModel):
msg: bool = True
class User(BaseModel):
id: int
email: str
password: str
app/endpoints/v1/insert_user.py¶
app/endpoints/v1/insert_user.py
¶from fastapi import Body
from fastapi import APIRouter
from fastapi_serviceutils.app import Endpoint
from fastapi_serviceutils.app import create_id_logger
from sqlalchemy import insert
from app.endpoints.v1.dbs import User
from app.endpoints.v1.models import InsertUser as Input
from app.endpoints.v1.models import Inserted as Output
ENDPOINT = Endpoint(router=APIRouter(), route='/insert_user', version='v1')
SUMMARY = 'Example request.'
EXAMPLE = Body(
...,
example={
'email': 'dummy.user@something.info'
'password': 'an3xampleP4ssword'
}
)
@ENDPOINT.router.post('/', response_model=Output, summary=SUMMARY)
async def insert_user(params: Input = EXAMPLE, request: Request) -> Output:
_, log = create_id_logger(request=request, endpoint=ENDPOINT)
log.debug(f'received request for {request.url} with params {params}.')
database = app.databases['userdb'].dbase
async with database.transaction():
query = insert(User).values(
email=params.email,
password=params.password
)
await database.execute(query)
return Output()
app/endpoints/v1/get_users.py¶
app/endpoints/v1/get_users.py
¶from fastapi import Body
from fastapi import APIRouter
from fastapi_serviceutils.app import Endpoint
from fastapi_serviceutils.app import create_id_logger
from app.endpoints.v1.dbs import User
from app.endpoints.v1.models import User as Output
ENDPOINT = Endpoint(router=APIRouter(), route='/get_users', version='v1')
SUMMARY = 'Example request.'
@ENDPOINT.router.post('/', response_model=Output, summary=SUMMARY)
async def get_users(request: Request) -> List[Output]:
_, log = create_id_logger(request=request, endpoint=ENDPOINT)
log.debug(f'received request for {request.url}.')
database = app.databases['userdb'].dbase
async with database.transaction():
users = await database.fetch_all(User.__table__.select())
return users
app/endpoints/v1/__init__.py¶
Finally we include these endpoints to our ENDPOINTS
.
__init__.py
¶from fastapi_serviceutils.endpoints import set_version_endpoints
from app.endpoints.v1 import get_users
from app.endpoints.v1 import insert_user
ENDPOINTS = set_version_endpoints(
endpoints=[get_users, insert_user],
version='v1',
prefix_template='/api/{version}{route}'
)
__all__ = ['ENDPOINTS']
The rest of our service, like the main.py
, the __init__.py
files of
the modules, etc. have the same content as described in exampleservice
.