pizzatool/pizzatool/api_helpers.py

104 lines
3.8 KiB
Python

from fastapi import Depends, HTTPException, Response, status
from inspect import Parameter, Signature
from ormantic.exceptions import NoMatch
from sqlite3 import IntegrityError
def CRUDMapper(app, ORMClass):
name = ORMClass.Mapping.table_name
collection_path = '/%ss' % name
item_path = '/%ss/{id}' % name
@app.get(collection_path)
async def read_all():
return await ORMClass.objects.all()
@app.post(collection_path, status_code=status.HTTP_201_CREATED)
async def create(values: ORMClass, response: Response):
try:
item = await ORMClass.objects.create(**values.__dict__)
response.headers['Location'] = '%ss/%d' % (name, item.id)
return item
except IntegrityError:
raise HTTPException(status_code=status.HTTP_409_CONFLICT)
async def get_item(id: int):
try:
return await ORMClass.objects.get(id=id)
except NoMatch:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
@app.get(item_path)
async def read(item=Depends(get_item)):
return item
@app.put(item_path, status_code=status.HTTP_204_NO_CONTENT)
async def update(values: ORMClass, item=Depends(get_item)):
await item.update(**values.__dict__)
@app.delete(item_path, status_code=status.HTTP_204_NO_CONTENT)
async def delete(item=Depends(get_item)):
await item.delete()
def RelationshipMapper(app, ORMClass1, ORMClass2, ORMRelationship):
scope_name = ORMClass1.Mapping.table_name
item_name = ORMClass2.Mapping.table_name
collection_path = '/%ss/{id}/%ss' % (scope_name, item_name)
item_path = '/%ss/{id}/%ss/{id2}' % (scope_name, item_name)
async def get_scope(id: int):
try:
return await ORMClass1.objects.get(id=id)
except NoMatch:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
async def get_item(**kwargs):
try:
return await ORMClass2.objects.get(id=kwargs['%s_id' % item_name])
except NoMatch:
raise HTTPException(
status_code=status.HTTP_422_UNPROCESSABLE_ENTITY)
get_item.__signature__ = Signature(parameters=[Parameter(
'%s_id' % item_name, Parameter.KEYWORD_ONLY, annotation=int)])
async def get_relationship(id2: int, scope=Depends(get_scope)):
try:
return await ORMRelationship.objects.select_related(item_name) \
.get(id=id2, **{scope_name: scope})
except NoMatch:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
@app.get(collection_path)
async def read_all(scope=Depends(get_scope)):
return await ORMRelationship.objects.select_related(item_name) \
.filter(**{scope_name: scope}).all()
@app.post(collection_path, status_code=status.HTTP_201_CREATED)
async def create(
response: Response,
scope=Depends(get_scope),
item=Depends(get_item)):
try:
relationship = await ORMRelationship.objects.create(
**{scope_name: scope, item_name: item})
response.headers['Location'] = \
'%ss/%d' % (item_name, relationship.id)
return relationship
except IntegrityError:
raise HTTPException(status_code=status.HTTP_409_CONFLICT)
@app.get(item_path)
async def read(relationship=Depends(get_relationship)):
return relationship
@app.put(item_path, status_code=status.HTTP_204_NO_CONTENT)
async def update(
item=Depends(get_item),
relationship=Depends(get_relationship)):
await relationship.update(**{item_name: item.id})
@app.delete(item_path, status_code=status.HTTP_204_NO_CONTENT)
async def delete(relationship=Depends(get_relationship)):
await relationship.delete()