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.dashboard import api as dashboard_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
|
||||
|
||||
logging.basicConfig(level=conf.gisaf.debugLevel)
|
||||
|
@ -46,3 +47,4 @@ app.include_router(geoapi, prefix="/api/gj")
|
|||
app.include_router(admin_api, prefix="/api/admin")
|
||||
app.include_router(dashboard_api, prefix="/api/dashboard")
|
||||
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