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.