Add download api (CSV)
This commit is contained in:
parent
8b7081df67
commit
d09099acac
2 changed files with 80 additions and 1 deletions
77
src/gisaf/api/download.py
Normal file
77
src/gisaf/api/download.py
Normal file
|
@ -0,0 +1,77 @@
|
||||||
|
import logging
|
||||||
|
import io
|
||||||
|
from typing import Annotated
|
||||||
|
|
||||||
|
from fastapi import (Depends, APIRouter, HTTPException, status, Response)
|
||||||
|
from fastapi.responses import FileResponse, StreamingResponse
|
||||||
|
from sqlmodel import select
|
||||||
|
from sqlalchemy.orm import selectinload, joinedload
|
||||||
|
|
||||||
|
from gisaf.database import pandas_query, fastapi_db_session as db_session
|
||||||
|
from gisaf.models.geo_models_base import GeoModel, PlottableModel
|
||||||
|
from gisaf.security import (
|
||||||
|
Token, authenticate_user, get_current_active_user, create_access_token,
|
||||||
|
)
|
||||||
|
from gisaf.models.authentication import (User, UserRead, Role, RoleRead)
|
||||||
|
from gisaf.registry import registry, NotInRegistry
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
api = APIRouter(
|
||||||
|
tags=["download"],
|
||||||
|
# dependencies=[Depends(get_token_header)],
|
||||||
|
responses={404: {"description": "Not found"}},
|
||||||
|
)
|
||||||
|
|
||||||
|
@api.get('/csv/{store}/{model_id}/{value}/{resample}',
|
||||||
|
responses={
|
||||||
|
200: {
|
||||||
|
"content": {
|
||||||
|
"text/csv": {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
async def download_csv(
|
||||||
|
store: str, model_id: int, value: str, resample: str,
|
||||||
|
db_session: db_session,
|
||||||
|
user: Annotated[UserRead, Depends(get_current_active_user)]
|
||||||
|
) -> StreamingResponse:
|
||||||
|
try:
|
||||||
|
store_record = registry.stores.loc[store]
|
||||||
|
model: type[GeoModel] = store_record.model
|
||||||
|
values_model = registry.values_for_model[model][0]
|
||||||
|
except KeyError:
|
||||||
|
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
|
||||||
|
## Check if there's a custom getter
|
||||||
|
custom_getter = getattr(values_model, f'get_{value}', None)
|
||||||
|
if custom_getter:
|
||||||
|
df = await custom_getter(model_id)
|
||||||
|
else:
|
||||||
|
df = await values_model.get_as_dataframe(model_id=model_id, with_only_columns=[value])
|
||||||
|
if len(df) == 0:
|
||||||
|
raise HTTPException(status.HTTP_204_NO_CONTENT)
|
||||||
|
if resample and resample != '0':
|
||||||
|
value_defs = [v for v in values_model.values if v['name'] == value]
|
||||||
|
if len(value_defs) > 0 and 'agg' in value_defs[0]:
|
||||||
|
resampling_method = value_defs[0]['agg']
|
||||||
|
else:
|
||||||
|
resampling_method = 'mean'
|
||||||
|
df = df.resample(resample).agg(resampling_method)
|
||||||
|
if len(df) > 0:
|
||||||
|
df.reset_index(inplace=True)
|
||||||
|
query = select(model).where(model.id == model_id).options(
|
||||||
|
*(joinedload(jt) for jt in model.selectinload()))
|
||||||
|
response = await db_session.exec(query)
|
||||||
|
item = response.one()
|
||||||
|
filename = f'"{item.caption}-{value}-{resample}.csv"'
|
||||||
|
filename = f'{item.__class__.__name__}-{value}-{resample}.csv'
|
||||||
|
stream = io.StringIO()
|
||||||
|
df.reset_index().to_csv(stream,
|
||||||
|
index=False,
|
||||||
|
date_format='%d/%m/%Y %H:%M',
|
||||||
|
float_format=values_model.float_format)
|
||||||
|
response = Response(stream.getvalue(),
|
||||||
|
headers={
|
||||||
|
'Content-Disposition': f"attachment; filename={filename}"
|
||||||
|
})
|
||||||
|
return response
|
|
@ -14,6 +14,7 @@ from gisaf.api.geoapi import api as geoapi
|
||||||
from gisaf.api.admin import api as admin_api
|
from gisaf.api.admin import api as admin_api
|
||||||
from gisaf.api.dashboard import api as dashboard_api
|
from gisaf.api.dashboard import api as dashboard_api
|
||||||
from gisaf.api.map import api as map_api
|
from gisaf.api.map import api as map_api
|
||||||
|
from gisaf.api.download import api as download_api
|
||||||
from gisaf.plugins import manager as plugin_manger
|
from gisaf.plugins import manager as plugin_manger
|
||||||
|
|
||||||
logging.basicConfig(level=conf.gisaf.debugLevel)
|
logging.basicConfig(level=conf.gisaf.debugLevel)
|
||||||
|
@ -45,4 +46,5 @@ app.include_router(api, prefix="/api")
|
||||||
app.include_router(geoapi, prefix="/api/gj")
|
app.include_router(geoapi, prefix="/api/gj")
|
||||||
app.include_router(admin_api, prefix="/api/admin")
|
app.include_router(admin_api, prefix="/api/admin")
|
||||||
app.include_router(dashboard_api, prefix="/api/dashboard")
|
app.include_router(dashboard_api, prefix="/api/dashboard")
|
||||||
app.include_router(map_api, prefix='/api/map')
|
app.include_router(map_api, prefix='/api/map')
|
||||||
|
app.include_router(download_api, prefix='/api/download')
|
Loading…
Add table
Add a link
Reference in a new issue