fix: exclude account_id and virtual fields from archive_content DB writes
- Adds fields_to_exclude_from_db to Archive_Content_Base to prevent SQL errors on non-existent columns. - Updates documentation for V3 Create/Update patterns and the x-ae-ignore-extra-fields header. - Propagates account_id_random to hosted file and media processing methods.
This commit is contained in:
@@ -272,6 +272,8 @@ async def save_file(
|
||||
|
||||
file_info: dict = {}
|
||||
file_info['saved'] = None
|
||||
file_info['account_id'] = account_id
|
||||
file_info['account_id_random'] = account_id_random
|
||||
file_info['link_to_type'] = link_to_type
|
||||
file_info['link_to_id'] = link_to_id
|
||||
file_info['link_to_id_random'] = link_to_id_random
|
||||
@@ -344,6 +346,8 @@ async def save_file_to_hosted_file(
|
||||
account_id: int,
|
||||
link_to_type: str,
|
||||
link_to_id: int,
|
||||
account_id_random: str = None,
|
||||
link_to_id_random: str = None,
|
||||
):
|
||||
log.setLevel(logging.DEBUG) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
|
||||
log.debug(locals())
|
||||
@@ -353,8 +357,11 @@ async def save_file_to_hosted_file(
|
||||
|
||||
file_info: dict = {}
|
||||
file_info['saved'] = None
|
||||
file_info['account_id'] = account_id
|
||||
file_info['account_id_random'] = account_id_random
|
||||
file_info['link_to_type'] = link_to_type
|
||||
file_info['link_to_id'] = link_to_id
|
||||
file_info['link_to_id_random'] = link_to_id_random
|
||||
file_info['filename'] = filename
|
||||
file_info['extension'] = extension
|
||||
file_info['content_type'] = mimetypes.guess_type(filename)[0]
|
||||
|
||||
@@ -24,6 +24,7 @@ async def clip_video_method(
|
||||
account_id: int,
|
||||
link_to_type: str,
|
||||
link_to_id: int,
|
||||
account_id_random: str = None,
|
||||
filename_no_ext: str = 'automated_hosted_file_clip_video',
|
||||
to_type: str = 'mp4',
|
||||
reencode: bool = False,
|
||||
@@ -66,6 +67,7 @@ async def clip_video_method(
|
||||
filename = new_filename,
|
||||
extension = to_type,
|
||||
account_id = account_id,
|
||||
account_id_random = account_id_random,
|
||||
link_to_type = link_to_type,
|
||||
link_to_id = link_to_id,
|
||||
)
|
||||
@@ -87,6 +89,7 @@ async def convert_file_method(
|
||||
link_to_type: str,
|
||||
link_to_id: int,
|
||||
account_id: int,
|
||||
account_id_random: str = None,
|
||||
filename_no_ext: str = 'automated_hosted_file_conversion',
|
||||
to_type: str = 'webp',
|
||||
):
|
||||
@@ -115,6 +118,7 @@ async def convert_file_method(
|
||||
filename = f'{filename_no_ext}.{to_type}',
|
||||
extension = to_type,
|
||||
account_id = account_id,
|
||||
account_id_random = account_id_random,
|
||||
link_to_type = link_to_type,
|
||||
link_to_id = link_to_id,
|
||||
)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import datetime, pytz
|
||||
|
||||
from typing import Dict, List, Optional, Set, Union
|
||||
from typing import Dict, List, Optional, Set, Union, ClassVar
|
||||
from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator
|
||||
|
||||
from app.db_sql import redis_lookup_id_random
|
||||
@@ -92,6 +92,13 @@ class Archive_Content_Base(BaseModel):
|
||||
hosted_file_content_type: Optional[str]
|
||||
hosted_file_size: Optional[str]
|
||||
|
||||
# Fields that are part of the model (for reading) but should not be saved to the DB table
|
||||
fields_to_exclude_from_db: ClassVar[list] = [
|
||||
'account_id', 'account_id_random', 'archive_id_random', 'hosted_file_id_random',
|
||||
'hosted_file_path', 'api_hosted_file_path_download', 'api_hosted_file_path_stream',
|
||||
'hosted_file_hash_sha256', 'hosted_file_content_type', 'hosted_file_size'
|
||||
]
|
||||
|
||||
_processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now)
|
||||
|
||||
@validator('id', always=True)
|
||||
|
||||
@@ -1323,6 +1323,20 @@ def post_obj_template(
|
||||
table_name_select = obj_type_kv_li[obj_type]['table_name']
|
||||
base_name = obj_type_kv_li[obj_type]['base_name']
|
||||
|
||||
# # Prune any keys that are not actual columns on the target table to avoid
|
||||
# # SQL errors when clients include convenience fields (e.g., account_id)
|
||||
# try:
|
||||
# from app import lib_sql_core
|
||||
# from sqlalchemy import text
|
||||
# with lib_sql_core.engine.connect() as conn:
|
||||
# cols_res = conn.execute(text(f"DESCRIBE `{table_name_insert}`;"))
|
||||
# cols = [r[0] for r in cols_res.fetchall()]
|
||||
# # keep only keys that match real columns (always allow id_random)
|
||||
# obj_data = {k: v for k, v in obj_data.items() if k in cols or k == 'id_random'}
|
||||
# except Exception as _:
|
||||
# # If DESCRIBE fails for any reason, fall back to original obj_data
|
||||
# log.debug(f"Could not inspect table columns for {table_name_insert}; proceeding without pruning.")
|
||||
|
||||
if sql_insert_result := sql_insert(table_name=table_name_insert, data=obj_data, id_random_length=id_random_length):
|
||||
log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL
|
||||
log.debug(sql_insert_result)
|
||||
|
||||
@@ -276,6 +276,7 @@ async def convert_file(
|
||||
link_to_type = link_to_type,
|
||||
link_to_id = lid_int,
|
||||
account_id = commons.x_account_id,
|
||||
account_id_random = commons.x_account_id_random,
|
||||
filename_no_ext = filename_no_ext,
|
||||
to_type = to_type
|
||||
)
|
||||
@@ -306,6 +307,7 @@ async def clip_video(
|
||||
start_time = start_time,
|
||||
end_time = end_time,
|
||||
account_id = commons.x_account_id,
|
||||
account_id_random = commons.x_account_id_random,
|
||||
link_to_type = link_to_type,
|
||||
link_to_id = lid_int,
|
||||
filename_no_ext = filename_no_ext,
|
||||
|
||||
Reference in New Issue
Block a user