General bug fixes and clean up. Starting on a better version 2 of the CRUD endpoints.
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
import datetime, json, time
|
||||
#from datetime import datetime, time, timedelta
|
||||
from fastapi import APIRouter, Body, Depends, Header, HTTPException, Query, Response, status
|
||||
from fastapi.responses import FileResponse
|
||||
from pydantic import BaseModel, EmailStr, Field
|
||||
from typing import Dict, List, Optional, Set, Union
|
||||
|
||||
@@ -65,7 +66,8 @@ from app.models.user_role_models import *
|
||||
|
||||
from app.models.e_stripe_models import *
|
||||
|
||||
obj_type_li = {}
|
||||
obj_type_kv_li = {} # New 2024-04-23
|
||||
obj_type_li = {} # Old...
|
||||
|
||||
#obj_type_li['cfg_flask'] = {'table_name': 'cfg_flask', 'base_name': Cfg_Flask_Base}
|
||||
|
||||
@@ -178,7 +180,7 @@ obj_type_li['post'] = {'table_name': 'v_post', 'tbl_name_update': 'post', 'base_
|
||||
obj_type_li['post_comment'] = {'table_name': 'v_post_comment', 'tbl_name_update': 'post_comment', 'base_name': Post_Comment_Base} # NOTE check view name: *_detail?
|
||||
obj_type_li['product'] = {'table_name': 'v_product', 'tbl_name_update': 'product', 'base_name': Product_Base}
|
||||
|
||||
obj_type_li['sponsorship'] = {'table_name': 'v_sponsorship', 'tbl_name_update': 'sponsorship', 'base_name': Sponsorship_Base} # NOTE check view name: *_detail?
|
||||
obj_type_li['sponsorship'] = {'table_name': 'v_sponsorship', 'tbl_name_update': 'sponsorship', 'base_name': Sponsorship_Base, 'tbl': 'v_sponsorship', 'tbl': 'v_sponsorship', 'mdl': Sponsorship_Base } # NOTE check view name: *_detail?
|
||||
obj_type_li['sponsorship_cfg'] = {'table_name': 'v_sponsorship_cfg', 'tbl_name_update': 'sponsorship_cfg', 'base_name': Sponsorship_Cfg_Base}
|
||||
|
||||
#obj_type_li['stripe_customer'] = {'table_name': 'stripe_customer', 'tbl_name_update': 'stripe_customer', 'base_name': Stripe_Customer_Base}
|
||||
@@ -230,6 +232,9 @@ async def get_obj_li(
|
||||
# Get the "json" param from the query string. This is a JSON formatted string of the data to be inserted.
|
||||
jp: Optional[Union[str, None]] = None,
|
||||
|
||||
file_type: str = 'CSV', # CSV, Excel
|
||||
return_file: Optional[bool] = False,
|
||||
|
||||
commons: Common_Route_Params = Depends(common_route_params),
|
||||
):
|
||||
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
|
||||
@@ -396,6 +401,7 @@ async def get_obj_li(
|
||||
|
||||
if sql_result:
|
||||
if isinstance(sql_result, list):
|
||||
log.setLevel(logging.DEBUG)
|
||||
resp_data_li = []
|
||||
for record in sql_result:
|
||||
if base_name:
|
||||
@@ -405,7 +411,91 @@ async def get_obj_li(
|
||||
log.warning('base_name model was not found. Returning raw data.')
|
||||
resp_data = record
|
||||
resp_data_li.append(resp_data)
|
||||
return mk_resp(data=resp_data_li, response=commons.response)
|
||||
column_name_li = list(sql_result[0].keys()) # This should be the same for all records in the list.
|
||||
|
||||
if return_file:
|
||||
log.setLevel(logging.DEBUG)
|
||||
|
||||
|
||||
# We want to handle any field that has a suffix of _json. It should be expanded into a list of fields that are prefixed with the original field name minus _json.
|
||||
# This will also allow us to export the data to a CSV or Excel file with the correct column names.
|
||||
# additional_json_field_list_for_export = []
|
||||
new_resp_data_li = []
|
||||
for record in resp_data_li:
|
||||
new_record = record.copy()
|
||||
for field_name in record.keys():
|
||||
field_value = record[field_name]
|
||||
if field_name.endswith('li_json') and record[field_name]:
|
||||
log.info(f'Found a field that ends with li_json: {field_name}')
|
||||
log.info(f'Field value is a list??: {field_value}')
|
||||
|
||||
# field_value = json.loads(record[key]) # Convert the string to a list of dictionaries
|
||||
|
||||
|
||||
# Example JSON data: {'facebook': 'https://www.facebook.com/example', 'twitter': 'https://twitter.com/example', 'instagram': 'https://www.instagram.com/example/', 'linkedin': 'https://www.linkedin.com/school/example', 'org': 'https://example.com/'}
|
||||
# Example new fields: social__facebook, social__twitter, social__instagram, social__linkedin, social__org
|
||||
|
||||
if isinstance(field_value, list):
|
||||
# Loop through the list of dictionaries
|
||||
log.info(f'Field value is a list: {field_value}')
|
||||
for item in field_value:
|
||||
# item = json.loads(item) # Convert the string to a dictionary
|
||||
for key, value in item.items():
|
||||
new_field_name = field_name[:-8]+'__'+key
|
||||
new_record[new_field_name] = value
|
||||
else:
|
||||
# Loop through key value pairs in the dictionary
|
||||
log.info(f'Field value is a dict: {field_value}')
|
||||
for key, value in field_value.items():
|
||||
new_field_name = field_name[:-8]+'__'+key
|
||||
new_record[new_field_name] = value
|
||||
|
||||
# Create a new field for each and value to the record
|
||||
# new_field_name = key[:-8]+'__cust_li'
|
||||
# new_record[new_field_name] = record[key]
|
||||
|
||||
new_record.pop(field_name) # Remove the original field
|
||||
elif field_name.endswith('_json') and record[field_name]:
|
||||
log.info(f'Found a field that ends with _json: {field_name}')
|
||||
log.info(f'Field value is a dict???: {field_value}')
|
||||
|
||||
for key, value in field_value.items():
|
||||
new_field_name = field_name[:-5]+'__'+key
|
||||
new_record[new_field_name] = value
|
||||
|
||||
new_record.pop(field_name) # Remove the original field
|
||||
elif field_name.endswith('li_json') or field_name.endswith('_json'):
|
||||
log.info(f'Found a field that ends with li_json or _json but no value: {field_name}')
|
||||
|
||||
new_record.pop(field_name) # Remove the original field
|
||||
new_resp_data_li.append(new_record)
|
||||
|
||||
|
||||
datetime_format='%Y-%m-%d_%H%M'
|
||||
|
||||
# current_datetime = datetime.datetime.now() # Servers timezone (Eastern)
|
||||
current_datetime_utc = datetime.datetime.utcnow() # UTC timezone
|
||||
current_datetime_utc = current_datetime_utc.strftime(datetime_format)
|
||||
filename = f'{obj_name}_list_{current_datetime_utc}'
|
||||
if file_type == 'CSV':
|
||||
filename_w_ext = filename+'.csv'
|
||||
elif file_type == 'Excel':
|
||||
filename_w_ext = filename+'.xlsx'
|
||||
|
||||
log.setLevel(logging.INFO)
|
||||
if result := create_export_file(data_dict_list=new_resp_data_li, column_name_li=[], subdir_path=obj_name, filename=filename, rm_id=True, export_type=file_type):
|
||||
log.info(f'Export file created and saved: {result}')
|
||||
else:
|
||||
log.error('Something went wrong while creating or saving the export file')
|
||||
tmp_file_path = result
|
||||
|
||||
log.info(f'Filename: {filename_w_ext}')
|
||||
if full_tmp_path := return_full_tmp_path(full_tmp_path=tmp_file_path):
|
||||
return FileResponse(path=full_tmp_path, filename=filename_w_ext)
|
||||
|
||||
else:
|
||||
return mk_resp(data=resp_data_li, response=commons.response)
|
||||
|
||||
else:
|
||||
status_message='Not Implemented (sort of). Attempted to process this request. Got a SQL result, but the returned data was unexpected.'
|
||||
|
||||
@@ -1227,3 +1317,22 @@ def delete_obj_template(
|
||||
else:
|
||||
log.debug(sql_result)
|
||||
return mk_resp(data=False, status_code=404, response=response)
|
||||
|
||||
|
||||
|
||||
# New dynamic API CRUD endpoint
|
||||
# The POST data should be JSON formatted
|
||||
# @router.post('/query')
|
||||
# def query(
|
||||
# # qry JSON should contain these properties:
|
||||
# # list: for_obj_type, for_obj_id, tbl_view_name, base_name
|
||||
# # id: obj_id, tbl_view_name, base_name
|
||||
# qry: str,
|
||||
|
||||
# commons: Common_Route_Params = Depends(common_route_params),
|
||||
|
||||
# ):
|
||||
# log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
|
||||
# log.debug(locals())
|
||||
|
||||
# import urllib
|
||||
|
||||
1180
app/routers/api_crud_v2.py
Normal file
1180
app/routers/api_crud_v2.py
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user