Work on temporary hosted file downloads and export creation.
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
import secrets
|
import os, secrets
|
||||||
from pydantic import AnyHttpUrl, BaseSettings, EmailStr, HttpUrl, PostgresDsn, validator
|
from pydantic import AnyHttpUrl, BaseSettings, EmailStr, HttpUrl, PostgresDsn, validator
|
||||||
from typing import Any, Dict, List, Optional, Union
|
from typing import Any, Dict, List, Optional, Union
|
||||||
|
|
||||||
@@ -14,6 +14,20 @@ class Settings(BaseSettings):
|
|||||||
AETHER_DB_PASSWORD = 'xxx'
|
AETHER_DB_PASSWORD = 'xxx'
|
||||||
SQLALCHEMY_DATABASE_URI = 'mysql://'+AETHER_DB_USERNAME+':'+AETHER_DB_PASSWORD+'@'+AETHER_DB_SERVER+'/'+AETHER_DB_NAME
|
SQLALCHEMY_DATABASE_URI = 'mysql://'+AETHER_DB_USERNAME+':'+AETHER_DB_PASSWORD+'@'+AETHER_DB_SERVER+'/'+AETHER_DB_NAME
|
||||||
|
|
||||||
|
HTTP_STATUS_LI = {}
|
||||||
|
HTTP_STATUS_LI[200] = { 'name': 'OK', 'message': 'The request has succeeded.' }
|
||||||
|
HTTP_STATUS_LI[400] = { 'name': 'Bad Request', 'message': 'The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repeat the request without modifications.' }
|
||||||
|
HTTP_STATUS_LI[401] = { 'name': 'Unauthorized', 'message': 'The server could not verify that you are authorized to access the URL requested. You either supplied the wrong credentials (e.g. a bad password), or your browser does not understand how to supply the credentials required.' }
|
||||||
|
HTTP_STATUS_LI[402] = { 'name': 'Request Failed', 'message': 'The parameters were valid but the request failed.' }
|
||||||
|
HTTP_STATUS_LI[403] = { 'name': 'Forbidden', 'message': 'The server understood the request, but is refusing to fulfill it. Authorization will not help and the request SHOULD NOT be repeated. If the request method was not HEAD and the server wishes to make public why the request has not been fulfilled, it SHOULD describe the reason for the refusal in the entity. If the server does not wish to make this information available to the client, the status code 404 (Not Found) can be used instead.' }
|
||||||
|
HTTP_STATUS_LI[404] = { 'name': 'Not Found', 'message': 'The requested resource does not exist.' }
|
||||||
|
HTTP_STATUS_LI[409] = { 'name': 'Conflict', 'message': 'The request conflicts with another request (perhaps due to using the same idempotent key).' }
|
||||||
|
HTTP_STATUS_LI[429] = { 'name': 'Too Many Requests', 'message': 'Too many requests hit the API too quickly. We recommend an exponential backoff of your requests.' }
|
||||||
|
HTTP_STATUS_LI[500] = { 'name': 'Internal Server Error', 'message': 'The server encountered an unexpected condition which prevented it from fulfilling the request.' }
|
||||||
|
HTTP_STATUS_LI[502] = { 'name': 'Bad Gateway', 'message': 'The server, while acting as a gateway or proxy, received an invalid response from the upstream server it accessed in attempting to fulfill the request.' }
|
||||||
|
HTTP_STATUS_LI[503] = { 'name': 'Service Unavailable', 'message': 'The server is currently unable to handle the request due to a temporary overloading or maintenance of the server. The implication is that this is a temporary condition which will be alleviated after some delay. If known, the length of the delay MAY be indicated in a Retry-After header. If no Retry-After is given, the client SHOULD handle the response as it would for a 500 response.' }
|
||||||
|
HTTP_STATUS_LI[504] = { 'name': 'Gateway Timeout', 'message': 'The server, while acting as a gateway or proxy, did not receive a timely response from the upstream server specified by the URI (e.g. HTTP, FTP, LDAP) or some other auxiliary server (e.g. DNS) it needed to access in attempting to complete the request.' }
|
||||||
|
|
||||||
DB_CFG_FASTAPI_ID = 0
|
DB_CFG_FASTAPI_ID = 0
|
||||||
|
|
||||||
settings = Settings()
|
settings = Settings()
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
import datetime, jwt, pytz, redis, time
|
import datetime, jwt, os, pandas, pathlib, pytz, redis, time
|
||||||
from passlib.hash import argon2
|
from passlib.hash import argon2
|
||||||
|
|
||||||
from fastapi import APIRouter, Depends, Header, HTTPException, Response, status
|
from fastapi import APIRouter, Depends, Header, HTTPException, Response, status
|
||||||
@@ -111,3 +111,48 @@ def decode_jwt(
|
|||||||
except:
|
except:
|
||||||
return None
|
return None
|
||||||
# ### END ### API Lib General ### decode_jwt() ###
|
# ### END ### API Lib General ### decode_jwt() ###
|
||||||
|
|
||||||
|
|
||||||
|
# ### BEGIN ### API Lib General ### create_export() ###
|
||||||
|
# Updated 2021-07-14
|
||||||
|
@logger_reset
|
||||||
|
def create_export_file(
|
||||||
|
data_dict_list: list,
|
||||||
|
subdir_path: str,
|
||||||
|
filename: str,
|
||||||
|
export_type: str = 'CSV', # CSV, Excel
|
||||||
|
) -> bool:
|
||||||
|
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
|
||||||
|
log.debug(locals())
|
||||||
|
|
||||||
|
hosted_temp_path = 'admin/temp'
|
||||||
|
log.info(f'Hosted Temp Path: {hosted_temp_path}')
|
||||||
|
|
||||||
|
subdirectory_dest = os.path.join(hosted_temp_path, subdir_path)
|
||||||
|
log.debug(subdirectory_dest)
|
||||||
|
pathlib.Path(subdirectory_dest).mkdir(parents=True, exist_ok=True)
|
||||||
|
file_dest_w_subdir = os.path.join(subdirectory_dest, filename)
|
||||||
|
log.info(f'File Dest With Subdir: {file_dest_w_subdir}')
|
||||||
|
|
||||||
|
column_name_li = data_dict_list[0].keys()
|
||||||
|
log.debug(column_name_li)
|
||||||
|
|
||||||
|
data_dataframe = pandas.DataFrame(data_dict_list)
|
||||||
|
log.debug(data_dataframe)
|
||||||
|
|
||||||
|
try:
|
||||||
|
if export_type == 'CSV':
|
||||||
|
log.info('Saving dataframe to CSV file')
|
||||||
|
full_dest_path = file_dest_w_subdir+'.csv'
|
||||||
|
data_dataframe.to_csv(full_dest_path, columns=column_name_li, index=False)
|
||||||
|
elif export_type == 'Excel':
|
||||||
|
log.info('Saving dataframe to Excel file')
|
||||||
|
full_dest_path = file_dest_w_subdir+'.xlsx'
|
||||||
|
data_dataframe.to_excel(full_dest_path, columns=column_name_li, index=False) # sheet_name='Sheet_name_1'
|
||||||
|
except:
|
||||||
|
log.exception('Something went wrong while trying to save the export file.')
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
# ### END ### API Lib General ### create_export() ###
|
||||||
|
|||||||
@@ -33,7 +33,11 @@ print('### **** *** ** * The Aether FastAPI API app is loading... * ** *** ****
|
|||||||
#)
|
#)
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI(
|
||||||
|
title='Aether API',
|
||||||
|
description='One Sky IT\'s Aether API using FastAPI.',
|
||||||
|
version='5.7.0',
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
@lru_cache()
|
@lru_cache()
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|||||||
# import datetime, hashlib, os, pathlib, shutil, time
|
# import datetime, hashlib, os, pathlib, shutil, time
|
||||||
#from datetime import datetime, time, timedelta
|
#from datetime import datetime, time, timedelta
|
||||||
from fastapi import APIRouter, Body, Depends, File, Form, Header, HTTPException, Query, Response, status, UploadFile
|
from fastapi import APIRouter, Body, Depends, File, Form, Header, HTTPException, Query, Response, status, UploadFile
|
||||||
|
from fastapi.responses import FileResponse
|
||||||
from pydantic import BaseModel, EmailStr, Field
|
from pydantic import BaseModel, EmailStr, Field
|
||||||
from typing import Dict, List, Optional, Set, Union
|
from typing import Dict, List, Optional, Set, Union
|
||||||
|
|
||||||
@@ -428,3 +429,23 @@ async def get_hosted_file_obj(
|
|||||||
return mk_resp(data=hosted_file_dict, response=response)
|
return mk_resp(data=hosted_file_dict, response=response)
|
||||||
#return mk_resp(data=hosted_file_obj)
|
#return mk_resp(data=hosted_file_obj)
|
||||||
# ### END ### API Hosted File ### get_hosted_file_obj() ###
|
# ### END ### API Hosted File ### get_hosted_file_obj() ###
|
||||||
|
|
||||||
|
|
||||||
|
# ### BEGIN ### API Hosted File ### download_tmp() ###
|
||||||
|
# Updated 2021-11-23
|
||||||
|
@router.get('/download/{filename}', response_model=Resp_Body_Base)
|
||||||
|
async def download_tmp(
|
||||||
|
filename: str = Query(..., min_length=4, max_length=100),
|
||||||
|
# x_account_id: str = Header(...),
|
||||||
|
by_alias: Optional[bool] = True,
|
||||||
|
exclude_unset: Optional[bool] = True,
|
||||||
|
response: Response = Response,
|
||||||
|
):
|
||||||
|
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
|
||||||
|
log.debug(locals())
|
||||||
|
|
||||||
|
full_dest_path = 'admin/temp/order_line/order_line_list_2021-11-23_1310.xlsx'
|
||||||
|
filename = 'text.xlsx'
|
||||||
|
|
||||||
|
return FileResponse(full_dest_path, filename=filename)
|
||||||
|
# ### END ### API Hosted File ### download_tmp() ###
|
||||||
@@ -32,6 +32,7 @@ async def get_obj_id_order_line_list(
|
|||||||
limit: int = 50,
|
limit: int = 50,
|
||||||
by_alias: Optional[bool] = True,
|
by_alias: Optional[bool] = True,
|
||||||
exclude_unset: Optional[bool] = True,
|
exclude_unset: Optional[bool] = True,
|
||||||
|
create_export: Optional[bool] = False,
|
||||||
x_account_id: str = Header(..., min_length=11, max_length=22),
|
x_account_id: str = Header(..., min_length=11, max_length=22),
|
||||||
response: Response = Response,
|
response: Response = Response,
|
||||||
):
|
):
|
||||||
@@ -57,6 +58,7 @@ async def get_obj_id_order_line_list(
|
|||||||
limit = limit,
|
limit = limit,
|
||||||
):
|
):
|
||||||
order_line_result_list = []
|
order_line_result_list = []
|
||||||
|
data_dict_list_for_export = []
|
||||||
for order_line_rec in order_line_rec_list_result:
|
for order_line_rec in order_line_rec_list_result:
|
||||||
if not full_detail:
|
if not full_detail:
|
||||||
if load_order_line_result := load_order_line_obj(
|
if load_order_line_result := load_order_line_obj(
|
||||||
@@ -74,8 +76,11 @@ async def get_obj_id_order_line_list(
|
|||||||
order_line_rec = order_line_rec,
|
order_line_rec = order_line_rec,
|
||||||
by_alias = by_alias,
|
by_alias = by_alias,
|
||||||
exclude_unset = exclude_unset,
|
exclude_unset = exclude_unset,
|
||||||
# model_as_dict = model_as_dict,
|
model_as_dict = False,
|
||||||
):
|
):
|
||||||
|
if create_export:
|
||||||
|
data_dict = load_order_line_result.dict(by_alias=by_alias, exclude_unset=exclude_unset)
|
||||||
|
data_dict_list_for_export.append(data_dict)
|
||||||
order_line_result_list.append(load_order_line_result)
|
order_line_result_list.append(load_order_line_result)
|
||||||
else:
|
else:
|
||||||
order_line_result_list.append(None)
|
order_line_result_list.append(None)
|
||||||
@@ -87,5 +92,26 @@ async def get_obj_id_order_line_list(
|
|||||||
log.warning('Likely bad request')
|
log.warning('Likely bad request')
|
||||||
return mk_resp(data=False, status_code=400, response=response) # Bad Request
|
return mk_resp(data=False, status_code=400, response=response) # Bad Request
|
||||||
|
|
||||||
|
if create_export:
|
||||||
|
datetime_format='%Y-%m-%d_%H%M'
|
||||||
|
|
||||||
|
current_datetime = datetime.datetime.now()
|
||||||
|
# current_datetime_string = current_datetime.isoformat()
|
||||||
|
current_datetime_string = current_datetime.strftime(datetime_format)
|
||||||
|
filename = f'order_line_list_{current_datetime_string}'
|
||||||
|
create_export_file(data_dict_list=data_dict_list_for_export, subdir_path='order_line', filename=filename, export_type='Excel')
|
||||||
|
|
||||||
|
# print(response_data)
|
||||||
|
|
||||||
|
# full_file_path = 'admin/temp/export_test_1.csv'
|
||||||
|
# full_file_path_xlsx = 'admin/temp/export_test_1.xlsx'
|
||||||
|
# keys = response_data[0].keys()
|
||||||
|
# print(keys)
|
||||||
|
|
||||||
|
# order_line_obj_dataframe = pandas.DataFrame(response_data)
|
||||||
|
# print(order_line_obj_dataframe)
|
||||||
|
# order_line_obj_dataframe.to_csv(full_file_path, columns=keys, index=False)
|
||||||
|
# order_line_obj_dataframe.to_excel(full_file_path_xlsx, columns=keys, index=False) # sheet_name='Sheet_name_1'
|
||||||
|
|
||||||
return mk_resp(data=response_data)
|
return mk_resp(data=response_data)
|
||||||
# ### END ### API Order Line ### get_obj_id_order_line_list() ###
|
# ### END ### API Order Line ### get_obj_id_order_line_list() ###
|
||||||
|
|||||||
Reference in New Issue
Block a user