(api): Add document routes.

This commit is contained in:
2025-06-08 22:05:13 +10:00
parent aba73b8bba
commit 94bc8b6c21
3 changed files with 76 additions and 10 deletions

View File

@@ -11,6 +11,7 @@ from datamodels import DataModel
from constants import DATA_VERSION from constants import DATA_VERSION
from routes.stamps import routes as stamp_routes from routes.stamps import routes as stamp_routes
from routes.documents import routes as doc_routes
from routes.lib import dbvar, datamodelsv from routes.lib import dbvar, datamodelsv
sys.path.insert(0, os.path.join(os.getcwd())) sys.path.insert(0, os.path.join(os.getcwd()))
@@ -74,6 +75,7 @@ async def app_factory():
app.cleanup_ctx.append(attach_db) app.cleanup_ctx.append(attach_db)
app.router.add_get('/', test) app.router.add_get('/', test)
app.router.add_routes(stamp_routes) app.router.add_routes(stamp_routes)
app.router.add_routes(doc_routes)
return app return app

View File

@@ -83,9 +83,9 @@ class Document:
conds = [] conds = []
if document_id is not None: if document_id is not None:
conds.append(Doc.document_id == document_id) conds.append(Doc.document_id == int(document_id))
if seal is not None: if seal is not None:
conds.append(Doc.seal == seal) conds.append(Doc.seal == int(seal))
if created_before is not None: if created_before is not None:
cbefore = datetime.fromisoformat(created_before) cbefore = datetime.fromisoformat(created_before)
conds.append(Doc.created_at <= cbefore) conds.append(Doc.created_at <= cbefore)
@@ -96,9 +96,9 @@ class Document:
conds.append(Doc.metadata == metadata) conds.append(Doc.metadata == metadata)
query = data.Document.table.fetch_rows_where(*conds) query = data.Document.table.fetch_rows_where(*conds)
results = await query # results = await query
query = data.Document.table.select_where(*conds) # query = data.Document.table.select_where(*conds)
if stamp_type is not None: if stamp_type is not None:
query.join('document_stamps', using=('document_id',), join_type=JOINTYPE.LEFT) query.join('document_stamps', using=('document_id',), join_type=JOINTYPE.LEFT)
query.join( query.join(
@@ -119,7 +119,7 @@ class Document:
else: else:
rows = await query rows = await query
return [cls(app, row) for row in rows] return [cls(app, row) for row in sorted(rows, key=lambda row:row.created_at)]
@classmethod @classmethod
async def create(cls, app: web.Application, **kwargs: Unpack[DocCreateParams]) -> Self: async def create(cls, app: web.Application, **kwargs: Unpack[DocCreateParams]) -> Self:
@@ -147,7 +147,7 @@ class Document:
return cls(app, row) return cls(app, row)
async def get_stamps(self) -> List[Stamp]: async def get_stamps(self) -> List[Stamp]:
stamprows = await self.data.DocumentStamp.table.fetch_rows_where(document_id=self.row.document_id) stamprows = await self.data.DocumentStamp.table.fetch_rows_where(document_id=self.row.document_id).order_by('stamp_id')
return [Stamp(self.app, row) for row in stamprows] return [Stamp(self.app, row) for row in stamprows]
async def prepare(self) -> DocPayload: async def prepare(self) -> DocPayload:
@@ -191,6 +191,7 @@ class Document:
@routes.view('/documents') @routes.view('/documents')
@routes.view('/documents/')
class DocumentsView(web.View): class DocumentsView(web.View):
async def get(self): async def get(self):
request = self.request request = self.request
@@ -229,3 +230,64 @@ class DocumentsView(web.View):
document = await Document.create(self.request.app, **params) document = await Document.create(self.request.app, **params)
payload = await document.prepare() payload = await document.prepare()
return web.json_response(payload) return web.json_response(payload)
@routes.view('/documents/{document_id}')
@routes.view('/documents/{document_id}/')
class DocumentView(web.View):
async def resolve_document(self):
request = self.request
document_id = request.match_info['document_id']
document = await Document.fetch_from_id(request.app, int(document_id))
if document is None:
raise web.HTTPNotFound(text="No document exists with the given ID.")
return document
async def get(self):
doc = await self.resolve_document()
payload = await doc.prepare()
return web.json_response(payload)
async def patch(self):
doc = await self.resolve_document()
params = await self.request.json()
edit_data = {}
for key, value in params.items():
if key not in edit_fields:
raise web.HTTPBadRequest(text=f"You cannot update field '{key}' of Document!")
edit_data[key] = value
for key in edit_fields:
if key in self.request:
edit_data.setdefault(key, self.request[key])
await doc.edit(**edit_data)
payload = await doc.prepare()
return web.json_response(payload)
async def delete(self):
doc = await self.resolve_document()
payload = await doc.delete()
return web.json_response(payload)
# We have one prefix route, /documents/{document_id}/stamps
@routes.route('*', "/documents/{document_id}{tail:/stamps}")
@routes.route('*', "/documents/{document_id}{tail:/stamps/.*}")
async def document_stamps_route(request: web.Request):
document_id = request.match_info['document_id']
document = await Document.fetch_from_id(request.app, int(document_id))
if document is None:
raise web.HTTPNotFound(text="No document exists with the given ID.")
new_path = request.match_info['tail']
new_request = request.clone(rel_url=new_path)
new_request['document_id'] = document_id
match_info = await request.app.router.resolve(new_request)
if match_info.handler:
return await match_info.handler(new_request)
else:
raise web.HTTPNotFound()

View File

@@ -76,9 +76,9 @@ class Stamp:
query_args = {} query_args = {}
if stamp_id is not None: if stamp_id is not None:
query_args['stamp_id'] = stamp_id query_args['stamp_id'] = int(stamp_id)
if document_id is not None: if document_id is not None:
query_args['document_id'] = document_id query_args['document_id'] = int(document_id)
if stamp_type is not None: if stamp_type is not None:
typerows = await data.StampType.table.fetch_rows_where(stamp_type_name=stamp_type) typerows = await data.StampType.table.fetch_rows_where(stamp_type_name=stamp_type)
typeids = [row.stamp_type_id for row in typerows] typeids = [row.stamp_type_id for row in typerows]
@@ -86,7 +86,7 @@ class Stamp:
return [] return []
query_args['stamp_type'] = typeids query_args['stamp_type'] = typeids
results = await data.DocumentStamp.table.fetch_rows_where(**query_args) results = await data.DocumentStamp.table.fetch_rows_where(**query_args)
return [cls(app, row) for row in results] return [cls(app, row) for row in sorted(results, key=lambda row:row.stamp_id)]
@classmethod @classmethod
async def create( async def create(
@@ -150,7 +150,7 @@ class Stamp:
'pos_y': 'position_y', 'pos_y': 'position_y',
'rotation': 'rotation' 'rotation': 'rotation'
} }
for editkey, datakey in simple_keys.values(): for editkey, datakey in simple_keys.items():
if editkey in kwargs: if editkey in kwargs:
edit_args[datakey] = kwargs[editkey] edit_args[datakey] = kwargs[editkey]
@@ -165,6 +165,7 @@ class Stamp:
@routes.view('/stamps') @routes.view('/stamps')
@routes.view('/stamps/', name='stamps')
class StampsView(web.View): class StampsView(web.View):
async def get(self): async def get(self):
request = self.request request = self.request
@@ -221,6 +222,7 @@ class StampsView(web.View):
@routes.view('/stamps/{stamp_id}') @routes.view('/stamps/{stamp_id}')
@routes.view('/stamps/{stamp_id}/', name='stamp')
class StampView(web.View): class StampView(web.View):
async def resolve_stamp(self): async def resolve_stamp(self):