From 0f4b4d2f5192ed495fb103ba86f6b384ea9be740 Mon Sep 17 00:00:00 2001 From: Scott Idem Date: Tue, 24 Feb 2026 16:21:27 -0500 Subject: [PATCH] feat: Implement V3 ID Vision and fields_to_exclude_from_db across core models This commit refactors numerous Pydantic models to align with the V3 ID Vision standard, ensuring that primary and foreign key fields are represented as clean string IDs in the API. It also introduces and populates the ClassVar in each model to prevent view-only fields and linked objects from being inadvertently written to the database during PATCH/POST operations. Specifically, this includes: - Adding to exclude view-derived or joined fields such as , , nested objects (e.g., , ), and convenience fields (e.g., ). - Adjusting root validators to correctly map string IDs and strip internal integer IDs for API responses. - Resolving a KeyError by adding to . These changes are crucial for maintaining data integrity and consistency with the V3 API architecture. --- app/models/address_models.py | 7 +- app/models/common_field_schema.py | 1 + app/models/contact_models.py | 7 +- app/models/event_abstract_models.py | 28 +- app/models/event_badge_models.py | 12 +- app/models/event_cfg_models.py | 51 +++- app/models/event_device_models.py | 2 +- app/models/event_exhibit_models.py | 7 +- app/models/event_exhibit_tracking_models.py | 24 +- app/models/event_file_models.py | 18 +- app/models/event_location_models.py | 12 +- app/models/event_models.py | 11 + app/models/event_person_models.py | 261 ++++++++--------- app/models/event_person_profile_models.py | 137 ++++----- app/models/event_presentation_models.py | 26 +- app/models/event_presenter_models.py | 302 +++++++------------- app/models/event_registration_cfg_models.py | 42 ++- app/models/event_registration_models.py | 124 +++----- app/models/event_session_models.py | 1 + app/models/event_track_models.py | 101 +++---- app/models/organization_models.py | 7 +- app/models/person_models.py | 15 +- 22 files changed, 611 insertions(+), 585 deletions(-) diff --git a/app/models/address_models.py b/app/models/address_models.py index 69e142a..b24af71 100644 --- a/app/models/address_models.py +++ b/app/models/address_models.py @@ -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, root_validator from app.db_sql import get_id_random, redis_lookup_id_random @@ -120,6 +120,11 @@ class Address_Base(BaseModel): return values + # 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] = [ + 'country_subdivision_name', 'country_name' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False diff --git a/app/models/common_field_schema.py b/app/models/common_field_schema.py index 20788ff..0615d58 100644 --- a/app/models/common_field_schema.py +++ b/app/models/common_field_schema.py @@ -49,6 +49,7 @@ base_fields['event_person_tracking_id_random'] = xxx_id_random_field_schema base_fields['event_presentation_id_random'] = xxx_id_random_field_schema base_fields['event_presenter_id_random'] = xxx_id_random_field_schema base_fields['event_registration_id_random'] = xxx_id_random_field_schema +base_fields['event_registration_cfg_id_random'] = xxx_id_random_field_schema base_fields['event_session_id_random'] = xxx_id_random_field_schema base_fields['event_track_id_random'] = xxx_id_random_field_schema base_fields['flask_cfg_id_random'] = xxx_id_random_field_schema diff --git a/app/models/contact_models.py b/app/models/contact_models.py index 47f022e..771e970 100644 --- a/app/models/contact_models.py +++ b/app/models/contact_models.py @@ -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, root_validator from app.db_sql import get_id_random, redis_lookup_id_random @@ -139,6 +139,11 @@ class Contact_Base(BaseModel): return values + # 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] = [ + 'linked_address_id', 'timezone_name', 'address' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False diff --git a/app/models/event_abstract_models.py b/app/models/event_abstract_models.py index 6d20f66..1679ef5 100644 --- a/app/models/event_abstract_models.py +++ b/app/models/event_abstract_models.py @@ -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, root_validator from app.db_sql import redis_lookup_id_random @@ -27,6 +27,7 @@ class Event_Abstract_Base(BaseModel): id: Optional[str] = Field(None, **base_fields['event_abstract_id_random']) event_abstract_id: Optional[str] = Field(None, **base_fields['event_abstract_id_random']) + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) event_id: Optional[str] = Field(None, **base_fields['event_id_random']) event_person_id: Optional[str] = Field(None, **base_fields['event_person_id_random']) event_presentation_id: Optional[str] = Field(None, **base_fields['event_presentation_id_random']) @@ -96,6 +97,8 @@ class Event_Abstract_Base(BaseModel): values['id'] = rid values['event_abstract_id'] = rid + if a_rid := values.get('account_id_random'): + values['account_id'] = a_rid if e_rid := values.get('event_id_random'): values['event_id'] = e_rid if ep_rid := values.get('event_person_id_random'): @@ -110,12 +113,18 @@ class Event_Abstract_Base(BaseModel): values['grant_id'] = g_rid # 2. Prevent "Collision Population" - for k in ['id', 'event_abstract_id', 'event_id', 'event_person_id', 'event_presentation_id', 'event_presenter_id', 'event_session_id', 'grant_id']: + for k in ['id', 'event_abstract_id', 'account_id', 'event_id', 'event_person_id', 'event_presentation_id', 'event_presenter_id', 'event_session_id', 'grant_id']: if k in values and not isinstance(values[k], str) and values[k] is not None: del values[k] return values + # 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', 'event_session_code', 'event_session_name', + 'event_file_list', 'event_person', 'event_presenter_list' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False @@ -136,6 +145,7 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base): id: Optional[str] = Field(None, **base_fields['event_abstract_id_random']) event_abstract_id: Optional[str] = Field(None, **base_fields['event_abstract_id_random']) + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) event_id: Optional[str] = Field(None, **base_fields['event_id_random']) event_person_id: Optional[str] = Field(None, **base_fields['event_person_id_random']) event_presentation_id: Optional[str] = Field(None, **base_fields['event_presentation_id_random']) @@ -181,6 +191,8 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base): values['id'] = rid values['event_abstract_id'] = rid + if a_rid := values.get('account_id_random'): + values['account_id'] = a_rid if e_rid := values.get('event_id_random'): values['event_id'] = e_rid if ep_rid := values.get('event_person_id_random'): @@ -195,12 +207,17 @@ class Event_Abstract_Base_New(Core_Std_Obj_Base): values['grant_id'] = g_rid # 2. Prevent "Collision Population" - for k in ['id', 'event_abstract_id', 'event_id', 'event_person_id', 'event_presentation_id', 'event_presenter_id', 'event_session_id', 'grant_id']: + for k in ['id', 'event_abstract_id', 'account_id', 'event_id', 'event_person_id', 'event_presentation_id', 'event_presenter_id', 'event_session_id', 'grant_id']: if k in values and not isinstance(values[k], str) and values[k] is not None: del values[k] return values + # 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' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False @@ -246,4 +263,9 @@ class Event_Abstract_Ext(Event_Abstract_Base_New): # event_track: Optional[Event_Track_Base] # poc_event_person: Optional[Event_Person_Base] # Maybe change this to primary_event_person? # poc_person: Optional[Person_Base] # Maybe change this to primary_person? + + # 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] = Event_Abstract_Base_New.fields_to_exclude_from_db + [ + 'event_session_code', 'event_session_name', 'event_cfg', 'event_file_list', 'event_person' + ] # ### END ### API Event Abstract Models ### Event_Abstract_Ext() ### diff --git a/app/models/event_badge_models.py b/app/models/event_badge_models.py index 028c858..d5f5894 100644 --- a/app/models/event_badge_models.py +++ b/app/models/event_badge_models.py @@ -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, root_validator from app.db_sql import redis_lookup_id_random @@ -191,6 +191,11 @@ class Event_Badge_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + # 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', 'order', 'ticket_list', 'event_badge_template' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = True @@ -329,6 +334,11 @@ class Event_Badge_Basic_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + # 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', 'event_badge_template' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = True diff --git a/app/models/event_cfg_models.py b/app/models/event_cfg_models.py index 916ef40..ead1ce3 100644 --- a/app/models/event_cfg_models.py +++ b/app/models/event_cfg_models.py @@ -1,7 +1,7 @@ import datetime, pytz -from typing import Dict, List, Optional, Set, Union -from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator +from typing import Dict, List, Optional, Set, Union, ClassVar +from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator from app.db_sql import redis_lookup_id_random from app.lib_general import log, logging @@ -15,16 +15,40 @@ class Event_Cfg_Base(BaseModel): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - id_random: Optional[str] = Field( - # **base_fields['event_cfg_id_random'], - alias = 'event_cfg_id_random', - ) - id: Optional[int] = Field( - alias = 'event_cfg_id' - ) + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_cfg_id_random']) + event_cfg_id: Optional[str] = Field(None, **base_fields['event_cfg_id_random']) - event_id_random: Optional[str] - event_id: Optional[int] + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) + + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_cfg_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_cfg_id_random'): + values['id'] = rid + values['event_cfg_id'] = rid + + if a_rid := values.get('account_id_random'): + values['account_id'] = a_rid + if e_rid := values.get('event_id_random'): + values['event_id'] = e_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_cfg_id', 'account_id', 'event_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values enable: Optional[bool] enable_from: Optional[datetime.datetime] @@ -105,6 +129,11 @@ class Event_Cfg_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + # 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', 'event_id', 'event_registration_cfg' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = True diff --git a/app/models/event_device_models.py b/app/models/event_device_models.py index 5953560..c24b01d 100644 --- a/app/models/event_device_models.py +++ b/app/models/event_device_models.py @@ -148,7 +148,7 @@ class Event_Device_Base(BaseModel): return values # 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] = ['event_cfg', 'event_location'] + fields_to_exclude_from_db: ClassVar[list] = ['account_id', 'event_cfg', 'event_location'] class Config: underscore_attrs_are_private = True diff --git a/app/models/event_exhibit_models.py b/app/models/event_exhibit_models.py index 0d5a850..89b3d5e 100644 --- a/app/models/event_exhibit_models.py +++ b/app/models/event_exhibit_models.py @@ -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, root_validator from app.db_sql import redis_lookup_id_random @@ -143,6 +143,11 @@ class Event_Exhibit_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + # 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] = [ + 'event_exhibit_tracking_list' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = True diff --git a/app/models/event_exhibit_tracking_models.py b/app/models/event_exhibit_tracking_models.py index 5c3ebe8..38e26be 100644 --- a/app/models/event_exhibit_tracking_models.py +++ b/app/models/event_exhibit_tracking_models.py @@ -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, root_validator from app.db_sql import redis_lookup_id_random @@ -215,6 +215,28 @@ class Event_Exhibit_Tracking_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + # 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', + 'event_badge_pronouns', 'event_badge_pronouns_override', 'event_badge_informal_name', + 'event_badge_title_names', 'event_badge_given_name', 'event_badge_middle_name', + 'event_badge_family_name', 'event_badge_designations', + 'event_badge_professional_title', 'event_badge_professional_title_override', + 'event_badge_full_name', 'event_badge_full_name_override', + 'event_badge_affiliations', 'event_badge_affiliations_override', + 'event_badge_email', 'event_badge_email_override', + 'event_badge_phone', 'event_badge_phone_override', + 'event_badge_address_line_1', 'event_badge_address_line_2', 'event_badge_address_line_3', + 'event_badge_city', 'event_badge_county', 'event_badge_country_subdivision_code', + 'event_badge_state_province', 'event_badge_state_province_abb', 'event_badge_postal_code', + 'event_badge_country_alpha_2_code', 'event_badge_country', + 'event_badge_location', 'event_badge_location_override', + 'event_person_informal_name', 'event_person_given_name', 'event_person_family_name', + 'event_person_full_name', 'event_person_full_name_override', + 'event_person_affiliations', 'event_person_email', 'event_exhibit_name', + 'event_person' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = True diff --git a/app/models/event_file_models.py b/app/models/event_file_models.py index acf8da4..8cc7ca3 100644 --- a/app/models/event_file_models.py +++ b/app/models/event_file_models.py @@ -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, root_validator from app.db_sql import get_id_random, redis_lookup_id_random @@ -206,6 +206,22 @@ class Event_File_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + # 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', 'filename_no_ext', 'filename_w_ext', + 'hosted_file_hash_sha256', 'hosted_file_subdirectory_path', + 'hosted_file_content_type', 'hosted_file_size', + 'event_name', 'event_code', 'event_start_datetime', 'event_end_datetime', + 'event_location_code', 'event_location_name', 'event_presentation_code', + 'event_presentation_type_code', 'event_presentation_name', + 'event_presentation_start_datetime', 'event_presentation_end_datetime', + 'event_presenter_code', 'event_presenter_given_name', 'event_presenter_family_name', + 'event_presenter_full_name', 'event_presenter_email', 'event_session_code', + 'event_session_type_code', 'event_session_name', 'event_session_start_datetime', + 'event_session_end_datetime', 'event_track_code', 'event_track_name', + 'hosted_file' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False diff --git a/app/models/event_location_models.py b/app/models/event_location_models.py index 7dabfac..372fe6d 100644 --- a/app/models/event_location_models.py +++ b/app/models/event_location_models.py @@ -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, root_validator from app.db_sql import redis_lookup_id_random @@ -129,6 +129,16 @@ class Event_Location_Base(BaseModel): return values + # 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', + 'location_type', 'file_count', 'internal_use_count', 'event_file_id_li_json', 'file_count_all', + 'event_name', 'event_start_datetime', 'event_end_datetime', + 'event_abstract_list', 'event_device_list', 'event_file_list', + 'event_file_internal_use_list', 'event_presentation_list', + 'event_presenter_list', 'event_session_list', 'event_track_list' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False diff --git a/app/models/event_models.py b/app/models/event_models.py index 2670557..51fd1cd 100644 --- a/app/models/event_models.py +++ b/app/models/event_models.py @@ -228,6 +228,17 @@ class Event_Base(BaseModel): return str(v) return v + # Fields that are part of the model (for reading) but should not be saved to the DB table. + # These convenience fields and related objects are joined in the view. + fields_to_exclude_from_db: ClassVar[list] = [ + 'file_count', 'internal_use_count', 'event_file_id_li_json', 'file_count_all', + 'address_location', 'contact_1', 'contact_2', 'contact_3', + 'event_abstract_list', 'event_cfg', 'event_device_list', 'event_exhibit_list', + 'event_file_list', 'event_location_list', 'event_person_list', + 'event_presentation_list', 'event_presenter_list', 'event_session_list', + 'event_track_list', 'poc_person' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = True diff --git a/app/models/event_person_models.py b/app/models/event_person_models.py index 52a4737..51c5db5 100644 --- a/app/models/event_person_models.py +++ b/app/models/event_person_models.py @@ -1,7 +1,7 @@ import datetime, pytz -from typing import Dict, List, Optional, Set, Union -from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator +from typing import Dict, List, Optional, Set, Union, ClassVar +from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator from app.db_sql import redis_lookup_id_random from app.lib_general import log, logging @@ -22,40 +22,33 @@ class Event_Person_Base(BaseModel): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - id_random: Optional[str] = Field( - # **base_fields['event_person_id_random'], - alias = 'event_person_id_random', - ) - id: Optional[int] = Field( - alias = 'event_person_id' - ) + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_person_id_random']) + event_person_id: Optional[str] = Field(None, **base_fields['event_person_id_random']) - account_id_random: Optional[str] - account_id: Optional[int] + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) - event_id_random: Optional[str] - event_id: Optional[int] + event_badge_id: Optional[str] = Field(None, **base_fields['event_badge_id_random']) + event_badge_vendor_id: Optional[str] = Field(None, **base_fields['event_badge_id_random']) + event_badge_vip_id: Optional[str] = Field(None, **base_fields['event_badge_id_random']) - event_badge_id_random: Optional[str] # Default attendee badge - event_badge_id: Optional[int] + event_person_profile_id: Optional[str] = Field(None, **base_fields['event_person_profile_id_random']) + event_registration_id: Optional[str] = Field(None, **base_fields['event_registration_id_random']) + person_id: Optional[str] = Field(None, **base_fields['person_id_random']) + user_id: Optional[str] = Field(None, **base_fields['user_id_random']) - event_badge_vendor_id_random: Optional[str] # Additional vendor badge - event_badge_vendor_id: Optional[int] - - event_badge_vip_id_random: Optional[str] # Additional VIP badge - event_badge_vip_id: Optional[int] - - event_person_profile_id_random: Optional[str] - event_person_profile_id: Optional[int] - - event_registration_id_random: Optional[str] - event_registration_id: Optional[int] - - person_id_random: Optional[str] - person_id: Optional[int] - - user_id_random: Optional[str] - user_id: Optional[int] + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_person_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + event_badge_id_random: Optional[str] = Field(None, exclude=True) + event_badge_vendor_id_random: Optional[str] = Field(None, exclude=True) + event_badge_vip_id_random: Optional[str] = Field(None, exclude=True) + event_person_profile_id_random: Optional[str] = Field(None, exclude=True) + event_registration_id_random: Optional[str] = Field(None, exclude=True) + person_id_random: Optional[str] = Field(None, exclude=True) + user_id_random: Optional[str] = Field(None, exclude=True) external_id: Optional[str] # Generated internally or externally. Needs to be stable. It should not change. external_event_id: Optional[str] # Event ID generated by external system. Needs to be stable. It should not change. @@ -159,81 +152,54 @@ class Event_Person_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - #@validator('event_person_id_random', always=True) - def event_person_id_random_copy(cls, v, values, **kwargs): - if values['id_random']: - return values['id_random'] - return None + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_person_id_random'): + values['id'] = rid + values['event_person_id'] = rid + + if a_rid := values.get('account_id_random'): values['account_id'] = a_rid + if e_rid := values.get('event_id_random'): values['event_id'] = e_rid + if b_rid := values.get('event_badge_id_random'): values['event_badge_id'] = b_rid + if bv_rid := values.get('event_badge_vendor_id_random'): values['event_badge_vendor_id'] = bv_rid + if bvip_rid := values.get('event_badge_vip_id_random'): values['event_badge_vip_id'] = bvip_rid + if ep_rid := values.get('event_person_profile_id_random'): values['event_person_profile_id'] = ep_rid + if er_rid := values.get('event_registration_id_random'): values['event_registration_id'] = er_rid + if p_rid := values.get('person_id_random'): values['person_id'] = p_rid + if u_rid := values.get('user_id_random'): values['user_id'] = u_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_person_id', 'account_id', 'event_id', 'event_badge_id', 'event_badge_vendor_id', 'event_badge_vip_id', 'event_person_profile_id', 'event_registration_id', 'person_id', 'user_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values - @validator('id', always=True) - def event_person_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_person') - return None - - @validator('account_id', always=True) - def account_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('account_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='account') - return None - - @validator('event_id', always=True) - def event_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event') - return None - - @validator('event_badge_id', always=True) - def event_badge_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_badge_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_badge') - return None - - @validator('event_badge_vendor_id', always=True) - def event_badge_vendor_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_badge_vendor_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_badge') - return None - - @validator('event_badge_vip_id', always=True) - def event_badge_vip_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_badge_vip_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_badge') - return None - - @validator('event_person_profile_id', always=True) - def event_person_profile_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_person_profile_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_person_profile') - return None - - @validator('event_registration_id', always=True) - def event_registration_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_registration_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_registration') - return None - - @validator('person_id', always=True) - def person_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('person_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='person') - return None - - @validator('user_id', always=True) - def user_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('user_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='user') - return None + # 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] = [ + 'file_count', + 'informal_name', 'given_name', 'middle_name', 'family_name', 'full_name_override', 'full_name', + 'affiliations', 'email', 'website_url', + 'event_badge_informal_name', 'event_badge_given_name', 'event_badge_middle_name', + 'event_badge_family_name', 'event_badge_full_name', 'event_badge_full_name_override', + 'event_badge_affiliations', 'event_badge_email', 'event_badge_city', + 'event_badge_state_province', 'event_badge_country_alpha_2_code', 'event_badge_country', + 'event_person_informal_name', 'event_person_given_name', 'event_person_middle_name', + 'event_person_family_name', 'event_person_name_override', 'event_person_full_name', + 'event_person_affiliations', 'event_person_email', 'event_person_extended_json', + 'person_informal_name', 'person_given_name', 'person_middle_name', 'person_family_name', + 'person_full_name', 'person_full_name_override', 'person_affiliations', 'person_email', + 'user_email', 'user_name', 'user_username', + 'event_badge', 'event_badge_vendor', 'event_badge_vip', 'event_exhibit_list', + 'event_file_list', 'event_location_list', 'event_person_profile', + 'event_presentation_list', 'event_presenter_list', 'event_registration', + 'event_session', 'event_track', 'person', 'user' + ] class Config: underscore_attrs_are_private = True @@ -247,17 +213,17 @@ class Event_Person_New_Base(BaseModel): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - id_random: Optional[str] = Field( - **base_fields['event_person_id_random'], - alias = 'event_person_id_random', - ) - id: Optional[int] = Field( - alias = 'event_person_id' - ) - account_id_random: Optional[str] - account_id: Optional[int] - event_id_random: Optional[str] - event_id: Optional[int] + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_person_id_random']) + event_person_id: Optional[str] = Field(None, **base_fields['event_person_id_random']) + + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) + + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_person_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) extended_json: Optional[Union[Json, None]] @@ -319,32 +285,43 @@ class Event_Person_New_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - #@validator('event_person_id_random', always=True) - def event_person_id_random_copy(cls, v, values, **kwargs): - if values['id_random']: - return values['id_random'] - return None + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_person_id_random'): + values['id'] = rid + values['event_person_id'] = rid + + if a_rid := values.get('account_id_random'): + values['account_id'] = a_rid + if e_rid := values.get('event_id_random'): + values['event_id'] = e_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_person_id', 'account_id', 'event_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values - @validator('id', always=True) - def event_person_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_person') - return None - - @validator('account_id', always=True) - def account_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('account_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='account') - return None - - @validator('event_id', always=True) - def event_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event') - return None + # 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] = [ + 'informal_name', 'given_name', 'middle_name', 'family_name', 'full_name', + 'full_name_override', 'affiliations', 'email', 'website_url', 'state_province_name', + 'event_badge_informal_name', 'event_badge_given_name', 'event_badge_middle_name', + 'event_badge_family_name', 'event_badge_full_name', 'event_badge_full_name_override', + 'event_badge_affiliations', 'event_badge_email', 'event_badge_city', + 'event_badge_state_province', 'event_badge_country_alpha_2_code', 'event_badge_country', + 'event_person_informal_name', 'event_person_given_name', 'event_person_middle_name', + 'event_person_family_name', 'event_person_name_override', 'event_person_full_name', + 'event_person_affiliations', 'event_person_email', + 'person_given_name', 'person_middle_name', 'person_family_name', + 'person_full_name', 'person_full_name_override', 'new_password' + ] class Config: underscore_attrs_are_private = True diff --git a/app/models/event_person_profile_models.py b/app/models/event_person_profile_models.py index f6937c8..adb4f94 100644 --- a/app/models/event_person_profile_models.py +++ b/app/models/event_person_profile_models.py @@ -1,7 +1,7 @@ import datetime, pytz -from typing import Dict, List, Optional, Set, Union -from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator +from typing import Dict, List, Optional, Set, Union, ClassVar +from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator from app.db_sql import redis_lookup_id_random from app.lib_general import log, logging @@ -17,28 +17,23 @@ class Event_Person_Profile_Base(BaseModel): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - id_random: Optional[str] = Field( - **base_fields['event_person_profile_id_random'], - alias = 'event_person_profile_id_random', - ) - id: Optional[int] = Field( - alias = 'event_person_profile_id' - ) + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_person_profile_id_random']) + event_person_profile_id: Optional[str] = Field(None, **base_fields['event_person_profile_id_random']) - account_id_random: Optional[str] - account_id: Optional[int] + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + contact_id: Optional[str] = Field(None, **base_fields['contact_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) + event_person_id: Optional[str] = Field(None, **base_fields['event_person_id_random']) + organization_id: Optional[str] = Field(None, **base_fields['organization_id_random']) - contact_id_random: Optional[str] - contact_id: Optional[int] - - event_id_random: Optional[str] # Only in view - event_id: Optional[int] # Only in view - - event_person_id_random: Optional[str] # Only in view - event_person_id: Optional[int] # Only in view - - organization_id_random: Optional[str] - organization_id: Optional[int] + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_person_profile_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + contact_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + event_person_id_random: Optional[str] = Field(None, exclude=True) + organization_id_random: Optional[str] = Field(None, exclude=True) pronouns: Optional[str] # Preferred pronouns informal_name: Optional[str] @@ -65,21 +60,18 @@ class Event_Person_Profile_Base(BaseModel): email: Optional[str] website_url: Optional[str] - thumbnail_hosted_file_id: Optional[int] - thumbnail_hosted_file_id_random: Optional[str] + thumbnail_hosted_file_id: Optional[str] = Field(None, **base_fields['hosted_file_id_random']) thumbnail_path: Optional[str] thumbnail_bg_color: Optional[str] # photo_path: Optional[str] # photo_bg_color: Optional[str] - picture_hosted_file_id: Optional[int] - picture_hosted_file_id_random: Optional[str] + picture_hosted_file_id: Optional[str] = Field(None, **base_fields['hosted_file_id_random']) picture_path: Optional[str] picture_bg_color: Optional[str] - about_hosted_file_id: Optional[int] - about_hosted_file_id_random: Optional[str] + about_hosted_file_id: Optional[str] = Field(None, **base_fields['hosted_file_id_random']) about_path: Optional[str] email_allowed: Optional[bool] @@ -110,66 +102,37 @@ class Event_Person_Profile_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - #@validator('event_person_profile_id_random', always=True) - def event_person_profile_id_random_copy(cls, v, values, **kwargs): - if values['id_random']: - return values['id_random'] - return None + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_person_profile_id_random'): + values['id'] = rid + values['event_person_profile_id'] = rid + + if a_rid := values.get('account_id_random'): values['account_id'] = a_rid + if c_rid := values.get('contact_id_random'): values['contact_id'] = c_rid + if e_rid := values.get('event_id_random'): values['event_id'] = e_rid + if ep_rid := values.get('event_person_id_random'): values['event_person_id'] = ep_rid + if o_rid := values.get('organization_id_random'): values['organization_id'] = o_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_person_profile_id', 'account_id', 'contact_id', 'event_id', 'event_person_id', 'organization_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values - @validator('id', always=True) - def event_person_profile_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_person_profile') - return None - - @validator('account_id', always=True) - def account_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('account_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='account') - return None - - @validator('contact_id', always=True) - def contact_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('contact_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='contact') - return None - - @validator('organization_id', always=True) - def organization_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('organization_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='organization') - return None - - @validator('thumbnail_hosted_file_id', always=True) - def thumbnail_hosted_file_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values.get('thumbnail_hosted_file_id_random', None): - return redis_lookup_id_random(record_id_random=values['thumbnail_hosted_file_id_random'], table_name='thumbnail_hosted_file') - return None - - @validator('picture_hosted_file_id', always=True) - def picture_hosted_file_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values.get('picture_hosted_file_id_random', None): - return redis_lookup_id_random(record_id_random=values['picture_hosted_file_id_random'], table_name='picture_hosted_file') - return None - - @validator('about_hosted_file_id', always=True) - def about_hosted_file_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values.get('about_hosted_file_id_random', None): - return redis_lookup_id_random(record_id_random=values['about_hosted_file_id_random'], table_name='about_hosted_file') - return None + # 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', 'event_id', 'event_person_id', + 'full_name', 'full_name_override', 'display_name', + 'thumbnail_path', 'picture_path', 'about_path', + 'contact', 'event_cfg', 'organization' + ] class Config: underscore_attrs_are_private = True diff --git a/app/models/event_presentation_models.py b/app/models/event_presentation_models.py index 83d3239..691264b 100644 --- a/app/models/event_presentation_models.py +++ b/app/models/event_presentation_models.py @@ -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, root_validator from app.db_sql import redis_lookup_id_random @@ -22,12 +22,22 @@ class Event_Presentation_Base(BaseModel): id: Optional[str] = Field(None, **base_fields['event_presentation_id_random']) event_presentation_id: Optional[str] = Field(None, **base_fields['event_presentation_id_random']) + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) event_id: Optional[str] = Field(None, **base_fields['event_id_random']) event_abstract_id: Optional[str] = Field(None, **base_fields['event_abstract_id_random']) event_location_id: Optional[str] = Field(None, **base_fields['event_location_id_random']) event_session_id: Optional[str] = Field(None, **base_fields['event_session_id_random']) event_track_id: Optional[str] = Field(None, **base_fields['event_track_id_random']) + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_presentation_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + event_abstract_id_random: Optional[str] = Field(None, exclude=True) + event_location_id_random: Optional[str] = Field(None, exclude=True) + event_session_id_random: Optional[str] = Field(None, exclude=True) + event_track_id_random: Optional[str] = Field(None, exclude=True) + external_id: Optional[str] = Field( # alias = 'event_presentation_external_id' ) @@ -109,6 +119,8 @@ class Event_Presentation_Base(BaseModel): values['id'] = rid values['event_presentation_id'] = rid + if a_rid := values.get('account_id_random'): + values['account_id'] = a_rid if e_rid := values.get('event_id_random'): values['event_id'] = e_rid if ea_rid := values.get('event_abstract_id_random'): @@ -121,12 +133,22 @@ class Event_Presentation_Base(BaseModel): values['event_track_id'] = et_rid # 2. Prevent "Collision Population" - for k in ['id', 'event_presentation_id', 'event_id', 'event_abstract_id', 'event_location_id', 'event_session_id', 'event_track_id']: + for k in ['id', 'event_presentation_id', 'account_id', 'event_id', 'event_abstract_id', 'event_location_id', 'event_session_id', 'event_track_id']: if k in values and not isinstance(values[k], str) and values[k] is not None: del values[k] return values + # 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', 'file_count', + 'event_name', 'event_start_datetime', 'event_end_datetime', 'event_location_name', + 'event_session_type_code', 'event_session_name', 'event_session_start_datetime', + 'event_session_end_datetime', 'event_track_name', + 'poc_event_person', 'poc_person', 'event_abstract_list', 'event_file_list', + 'event_presenter_list', 'event_session' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False diff --git a/app/models/event_presenter_models.py b/app/models/event_presenter_models.py index b9e6dc8..bc24357 100644 --- a/app/models/event_presenter_models.py +++ b/app/models/event_presenter_models.py @@ -1,7 +1,7 @@ import datetime, pytz -from typing import Dict, List, Optional, Set, Union -from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator +from typing import Dict, List, Optional, Set, Union, ClassVar +from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator from app.db_sql import redis_lookup_id_random from app.lib_general import log, logging @@ -19,45 +19,32 @@ class Event_Presenter_Base(BaseModel): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - id_random: Optional[str] = Field( - # **base_fields['event_presenter_id_random'], - alias = 'event_presenter_id_random', - ) - id: Optional[int] = Field( - alias = 'event_presenter_id' - ) + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_presenter_id_random']) + event_presenter_id: Optional[str] = Field(None, **base_fields['event_presenter_id_random']) - account_id_random: Optional[str] - account_id: Optional[int] + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) + event_person_id: Optional[str] = Field(None, **base_fields['event_person_id_random']) + event_presentation_id: Optional[str] = Field(None, **base_fields['event_presentation_id_random']) + event_session_id: Optional[str] = Field(None, **base_fields['event_session_id_random']) + event_track_id: Optional[str] = Field(None, **base_fields['event_track_id_random']) + person_id: Optional[str] = Field(None, **base_fields['person_id_random']) + + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_presenter_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + event_person_id_random: Optional[str] = Field(None, exclude=True) + event_presentation_id_random: Optional[str] = Field(None, exclude=True) + event_session_id_random: Optional[str] = Field(None, exclude=True) + event_track_id_random: Optional[str] = Field(None, exclude=True) + person_id_random: Optional[str] = Field(None, exclude=True) external_id: Optional[str] code: Optional[str] - event_id_random: Optional[str] - event_id: Optional[int] - - # event_abstract_id_random: Optional[str] - # event_abstract_id: Optional[int] - - event_location_id_random: Optional[str] - event_location_id: Optional[int] - - event_person_id_random: Optional[str] - event_person_id: Optional[int] - - event_presentation_id_random: Optional[str] - event_presentation_id: Optional[int] - - event_session_id_random: Optional[str] - event_session_id: Optional[int] - - event_track_id_random: Optional[str] - event_track_id: Optional[int] - - person_id_random: Optional[str] - person_id: Optional[int] - for_type: Optional[str] for_id: Optional[int] @@ -193,58 +180,52 @@ class Event_Presenter_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - @validator('id', always=True) - def event_presenter_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_presenter') - return None + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_presenter_id_random'): + values['id'] = rid + values['event_presenter_id'] = rid + + if a_rid := values.get('account_id_random'): values['account_id'] = a_rid + if e_rid := values.get('event_id_random'): values['event_id'] = e_rid + if ep_rid := values.get('event_person_id_random'): values['event_person_id'] = ep_rid + if epr_rid := values.get('event_presentation_id_random'): values['event_presentation_id'] = epr_rid + if es_rid := values.get('event_session_id_random'): values['event_session_id'] = es_rid + if et_rid := values.get('event_track_id_random'): values['event_track_id'] = et_rid + if p_rid := values.get('person_id_random'): values['person_id'] = p_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_presenter_id', 'account_id', 'event_id', 'event_person_id', 'event_presentation_id', 'event_session_id', 'event_track_id', 'person_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values - @validator('account_id', always=True) - def account_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('account_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='account') - return None - - @validator('event_id', always=True) - def event_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event') - return None - - @validator('event_person_id', always=True) - def event_person_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_person_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_person') - return None - - @validator('event_presentation_id', always=True) - def event_presentation_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_presentation_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_presentation') - return None - - @validator('event_session_id', always=True) - def event_session_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_session_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_session') - return None - - @validator('person_id', always=True) - def person_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('person_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='person') - return None + # 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', 'file_count', 'event_file_id_li_json', + 'event_name', 'event_start_datetime', 'event_end_datetime', + 'event_location_code', 'event_location_name', + 'event_presentation_code', 'event_presentation_type_code', 'event_presentation_name', + 'event_presentation_start_datetime', 'event_presentation_end_datetime', + 'event_session_code', 'event_session_type_code', 'event_session_name', + 'event_session_start_datetime', 'event_session_end_datetime', + 'event_track_code', 'event_track_name', + 'person_external_id', 'person_external_sys_id', 'person_given_name', + 'person_family_name', 'person_professional_title', 'person_full_name', + 'person_affiliations', 'person_primary_email', 'person_passcode', + 'event_abstract', 'event_abstract_list', 'event_cfg', 'event_file_list', + 'event_person', 'event_presentation', 'event_session' + ] class Config: underscore_attrs_are_private = True - allow_population_by_field_name = True + allow_population_by_field_name = False fields = base_fields # ### END ### API Event Presenter Models ### Event_Presenter_Base() ### @@ -255,48 +236,28 @@ class Event_Presenter_Out_Base(BaseModel): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - id_random: Optional[str] = Field( - **base_fields['event_presenter_id_random'], - alias = 'event_presenter_id_random', - ) - id: Optional[int] = Field( - alias = 'event_presenter_id' - ) + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_presenter_id_random']) + event_presenter_id: Optional[str] = Field(None, **base_fields['event_presenter_id_random']) - account_id_random: Optional[str] - account_id: Optional[int] + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) + person_id: Optional[str] = Field(None, **base_fields['person_id_random']) + event_presentation_id: Optional[str] = Field(None, **base_fields['event_presentation_id_random']) + event_session_id: Optional[str] = Field(None, **base_fields['event_session_id_random']) + + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_presenter_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + person_id_random: Optional[str] = Field(None, exclude=True) + event_presentation_id_random: Optional[str] = Field(None, exclude=True) + event_session_id_random: Optional[str] = Field(None, exclude=True) external_id: Optional[str] code: Optional[str] - event_id_random: Optional[str] - event_id: Optional[int] - - # event_abstract_id_random: Optional[str] - # event_abstract_id: Optional[int] - - # event_location_id_random: Optional[str] - # event_location_id: Optional[int] - - # event_person_id_random: Optional[str] - # event_person_id: Optional[int] - - event_presentation_id_random: Optional[str] - event_presentation_id: Optional[int] - - event_session_id_random: Optional[str] - event_session_id: Optional[int] - - # event_track_id_random: Optional[str] - # event_track_id: Optional[int] - - person_id_random: Optional[str] - person_id: Optional[int] - - # for_type: Optional[str] - # for_id: Optional[int] - pronouns: Optional[str] # Preferred pronouns informal_name: Optional[str] # Informal or nick name they commonly go by @@ -311,38 +272,24 @@ class Event_Presenter_Out_Base(BaseModel): professional_title: Optional[str] # Professional title # title: Optional[str] # NOTE: Phasing out! Use *professional_title* instead. - # display_name: Optional[str] # NOTE: This will be changed to full_name_override to match event_badge, event_person_profile, and person - # BEGIN # Auto created name variations full_name: Optional[str] # title_names given_name middle_name family_name designations full_name_override: Optional[str] # Override full_name; Actual name shown for presenter - # degree: Optional[str] # NOTE: Phasing out! Use *designations* instead. - # degrees: Optional[str] # NOTE: Phasing out! Use *designations* instead. - # credentials: Optional[str] # NOTE: Phasing out! Use *designations* instead. - affiliations: Optional[str] # One or more affiliations with organizations, companies, and other groups # affiliation: Optional[str] # NOTE: Phasing out! Use *affiliations* instead. email: Optional[str] website_url: Optional[str] - # phone_li_json: Optional[Union[Json, None]] - # For social media in a JSON object format. The Aether standard field names should be used. Examples: url, url_text, icon, etc. social_li_json: Optional[Union[Json, None]] tagline: Optional[str] biography: Optional[str] - # picture_path: Optional[str] # Start using image_li_json instead - # picture_bg_color: Optional[str] - # For image files only in a JSON object format. The Aether standard field names should be used. Examples: url, url_text, alt_text, width, height, size (in bytes), etc. image_li_json: Optional[Union[Json, None]] # "headshot" is probably the most common - # media_li_json: Optional[Union[Json, None]] - - # role: Optional[str] data_json: Optional[Union[Json, None]] # For key value data. Careful with overwriting existing fields! cfg_json: Optional[Union[Json, None]] # Store per presenter config options like theme, language, etc @@ -356,13 +303,8 @@ class Event_Presenter_Out_Base(BaseModel): comments: Optional[str] enable: Optional[bool] - # enable_from: Optional[datetime.datetime] = None - # enable_to: Optional[datetime.datetime] = None hide: Optional[bool] - # public: Optional[bool] - # public_hide: Optional[bool] - # hide_event_launcher: Optional[bool] priority: Optional[bool] sort: Optional[int] # The presenter number if given @@ -372,24 +314,6 @@ class Event_Presenter_Out_Base(BaseModel): created_on: Optional[datetime.datetime] = None updated_on: Optional[datetime.datetime] = None - # Including convenience data - # This is only for convenience. Probably going to keep unless it causes a problem. - # event_name: Optional[str] - # event_start_datetime: Optional[datetime.datetime] - # event_end_datetime: Optional[datetime.datetime] - # event_location_code: Optional[str] - # event_location_name: Optional[str] - # event_presentation_code: Optional[str] - # event_presentation_type_code: Optional[str] - # event_presentation_name: Optional[str] - # event_presentation_start_datetime: Optional[datetime.datetime] - # event_presentation_end_datetime: Optional[datetime.datetime] - # event_session_code: Optional[str] - # event_session_type_code: Optional[str] - # event_session_name: Optional[str] - # event_session_start_datetime: Optional[datetime.datetime] - # event_session_end_datetime: Optional[datetime.datetime] - person_external_id: Optional[str] person_external_sys_id: Optional[str] person_given_name: Optional[str] @@ -404,50 +328,32 @@ class Event_Presenter_Out_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - @validator('id', always=True) - def event_presenter_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_presenter') - return None - - @validator('event_id', always=True) - def event_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event') - return None - - # @validator('event_person_id', always=True) - # def event_person_id_lookup(cls, v, values, **kwargs): - # if isinstance(v, int) and v > 0: return v - # elif id_random := values.get('event_person_id_random'): - # return redis_lookup_id_random(record_id_random=id_random, table_name='event_person') - # return None - - @validator('event_presentation_id', always=True) - def event_presentation_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_presentation_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_presentation') - return None - - @validator('event_session_id', always=True) - def event_session_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('event_session_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='event_session') - return None - - @validator('person_id', always=True) - def person_id_lookup(cls, v, values, **kwargs): - if isinstance(v, int) and v > 0: return v - elif id_random := values.get('person_id_random'): - return redis_lookup_id_random(record_id_random=id_random, table_name='person') - return None + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_presenter_id_random'): + values['id'] = rid + values['event_presenter_id'] = rid + + if a_rid := values.get('account_id_random'): values['account_id'] = a_rid + if e_rid := values.get('event_id_random'): values['event_id'] = e_rid + if epr_rid := values.get('event_presentation_id_random'): values['event_presentation_id'] = epr_rid + if es_rid := values.get('event_session_id_random'): values['event_session_id'] = es_rid + if p_rid := values.get('person_id_random'): values['person_id'] = p_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_presenter_id', 'account_id', 'event_id', 'event_presentation_id', 'event_session_id', 'person_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values class Config: underscore_attrs_are_private = True - allow_population_by_field_name = True + allow_population_by_field_name = False fields = base_fields # ### END ### API Event Presenter Models ### Event_Presenter_Base() ### diff --git a/app/models/event_registration_cfg_models.py b/app/models/event_registration_cfg_models.py index 7e4fdc6..8f25c29 100644 --- a/app/models/event_registration_cfg_models.py +++ b/app/models/event_registration_cfg_models.py @@ -1,8 +1,8 @@ from __future__ import annotations import datetime, hashlib, logging, os, pytz, redis, secrets -from typing import Dict, List, Optional, Set, Union -from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator +from typing import Dict, List, Optional, Set, Union, ClassVar +from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator from app.db_sql import redis_lookup_id_random from app.lib_general import log, logging @@ -14,6 +14,41 @@ class Event_Registration_Cfg_Base(BaseModel): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_registration_cfg_id_random']) + event_registration_cfg_id: Optional[str] = Field(None, **base_fields['event_registration_cfg_id_random']) + + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) + + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_registration_cfg_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_registration_cfg_id_random'): + values['id'] = rid + values['event_registration_cfg_id'] = rid + + if a_rid := values.get('account_id_random'): + values['account_id'] = a_rid + if e_rid := values.get('event_id_random'): + values['event_id'] = e_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_registration_cfg_id', 'account_id', 'event_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values + start_on: Optional[datetime.datetime] end_on: Optional[datetime.datetime] @@ -50,6 +85,9 @@ class Event_Registration_Cfg_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) + # 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] = [] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = True diff --git a/app/models/event_registration_models.py b/app/models/event_registration_models.py index 68955b6..18f45e7 100644 --- a/app/models/event_registration_models.py +++ b/app/models/event_registration_models.py @@ -1,7 +1,7 @@ import datetime, pytz -from typing import Dict, List, Optional, Set, Union -from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator +from typing import Dict, List, Optional, Set, Union, ClassVar +from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator from app.db_sql import redis_lookup_id_random from app.lib_general import * @@ -15,24 +15,23 @@ class Event_Registration_Base(BaseModel): log.setLevel(logging.INFO) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - id_random: Optional[str] = Field( - **base_fields['event_registration_id_random'], - alias = 'event_registration_id_random', - ) - id: Optional[int] = Field( - alias = 'event_registration_id' - ) + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_registration_id_random']) + event_registration_id: Optional[str] = Field(None, **base_fields['event_registration_id_random']) - account_id_random: Optional[str] - account_id: Optional[int] - event_id_random: Optional[str] - event_id: Optional[int] - organization_id_random: Optional[str] - organization_id: Optional[int] - contact_id_random: Optional[str] - contact_id: Optional[int] - person_id_random: Optional[str] - person_id: Optional[int] + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) + organization_id: Optional[str] = Field(None, **base_fields['organization_id_random']) + contact_id: Optional[str] = Field(None, **base_fields['contact_id_random']) + person_id: Optional[str] = Field(None, **base_fields['person_id_random']) + + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_registration_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + organization_id_random: Optional[str] = Field(None, exclude=True) + contact_id_random: Optional[str] = Field(None, exclude=True) + person_id_random: Optional[str] = Field(None, exclude=True) priority: Optional[bool] sort: Optional[int] @@ -48,69 +47,32 @@ class Event_Registration_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - #@validator('event_registration_id_random', always=True) - def event_registration_id_random_copy(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_registration_id_random'): + values['id'] = rid + values['event_registration_id'] = rid + + if a_rid := values.get('account_id_random'): values['account_id'] = a_rid + if e_rid := values.get('event_id_random'): values['event_id'] = e_rid + if o_rid := values.get('organization_id_random'): values['organization_id'] = o_rid + if c_rid := values.get('contact_id_random'): values['contact_id'] = c_rid + if p_rid := values.get('person_id_random'): values['person_id'] = p_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_registration_id', 'account_id', 'event_id', 'organization_id', 'contact_id', 'person_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values - if values['id_random']: - return values['id_random'] - return None - - @validator('id', always=True) - def event_registration_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['id_random']: - log.debug(values['id_random']) - return redis_lookup_id_random(record_id_random=values['id_random'], table_name='event_registration') - return None - - @validator('account_id', always=True) - def account_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['account_id_random']: - return redis_lookup_id_random(record_id_random=values['account_id_random'], table_name='account') - return None - - @validator('event_id', always=True) - def event_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['event_id_random']: - return redis_lookup_id_random(record_id_random=values['event_id_random'], table_name='event') - return None - - @validator('organization_id', always=True) - def organization_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['organization_id_random']: - return redis_lookup_id_random(record_id_random=values['organization_id_random'], table_name='organization') - return None - - @validator('contact_id', always=True) - def contact_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['contact_id_random']: - return redis_lookup_id_random(record_id_random=values['contact_id_random'], table_name='contact') - return None - - @validator('person_id', always=True) - def person_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['person_id_random']: - return redis_lookup_id_random(record_id_random=values['person_id_random'], table_name='person') - return None + # 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] = ['cfg', 'event_person_list'] class Config: underscore_attrs_are_private = True diff --git a/app/models/event_session_models.py b/app/models/event_session_models.py index b4b151c..c1c5830 100644 --- a/app/models/event_session_models.py +++ b/app/models/event_session_models.py @@ -216,6 +216,7 @@ class Event_Session_Base(BaseModel): # 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', 'file_count', 'internal_use_count', 'event_file_id_li_json', 'file_count_all', 'event_name', 'event_start_datetime', 'event_end_datetime', 'event_location_name', 'event_track_name', diff --git a/app/models/event_track_models.py b/app/models/event_track_models.py index 62ecbdd..a264d8d 100644 --- a/app/models/event_track_models.py +++ b/app/models/event_track_models.py @@ -1,7 +1,7 @@ import datetime, pytz -from typing import Dict, List, Optional, Set, Union -from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator +from typing import Dict, List, Optional, Set, Union, ClassVar +from pydantic import BaseModel, EmailStr, Field, Json, PrivateAttr, ValidationError, validator, root_validator from app.db_sql import redis_lookup_id_random from app.lib_general import log, logging @@ -15,17 +15,19 @@ class Event_Track_Base(BaseModel): log.setLevel(logging.WARNING) # DEBUG, INFO, WARNING, ERROR, EXCEPTION, CRITICAL log.debug(locals()) - id_random: Optional[str] = Field( - **base_fields['event_track_id_random'], - alias = 'event_track_id_random', - ) - id: Optional[int] = Field( - alias = 'event_track_id' - ) - event_id_random: Optional[str] - event_id: Optional[int] - event_location_id_random: Optional[str] # Can a location be assigned to one track? - event_location_id: Optional[int] # Can a location be assigned to one track? + # --- Standardized Vision IDs (Strings) --- + id: Optional[str] = Field(None, **base_fields['event_track_id_random']) + event_track_id: Optional[str] = Field(None, **base_fields['event_track_id_random']) + + account_id: Optional[str] = Field(None, **base_fields['account_id_random']) + event_id: Optional[str] = Field(None, **base_fields['event_id_random']) + event_location_id: Optional[str] = Field(None, **base_fields['event_location_id_random']) + + # --- Standardized Legacy / Internal IDs (Excluded) --- + id_random: Optional[str] = Field(None, alias='event_track_id_random', exclude=True) + account_id_random: Optional[str] = Field(None, exclude=True) + event_id_random: Optional[str] = Field(None, exclude=True) + event_location_id_random: Optional[str] = Field(None, exclude=True) lu_track_type_id: Optional[int] track_type_code: Optional[str] @@ -54,6 +56,11 @@ class Event_Track_Base(BaseModel): created_on: Optional[datetime.datetime] = None updated_on: Optional[datetime.datetime] = None + # Including convenience data + event_name: Optional[str] + event_start_datetime: Optional[datetime.datetime] + event_end_datetime: Optional[datetime.datetime] + # Including other related objects #event: Optional[Event_Base] event_abstract_list: Optional[list] # Optional[Event_Abstract_Base] @@ -66,45 +73,41 @@ class Event_Track_Base(BaseModel): _processed_at: datetime.datetime = PrivateAttr(default_factory=datetime.datetime.now) - #@validator('event_track_id_random', always=True) - def event_track_id_random_copy(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) + @root_validator(pre=True) + def map_v3_ids(cls, values): + """ + Vision Transformer: + Map DB keys to clean API keys and strip internal integers. + """ + # 1. Map Random Strings to Clean Names + if rid := values.get('id_random') or values.get('event_track_id_random'): + values['id'] = rid + values['event_track_id'] = rid + + if a_rid := values.get('account_id_random'): + values['account_id'] = a_rid + if e_rid := values.get('event_id_random'): + values['event_id'] = e_rid + if el_rid := values.get('event_location_id_random'): + values['event_location_id'] = el_rid + + # 2. Prevent "Collision Population" + for k in ['id', 'event_track_id', 'account_id', 'event_id', 'event_location_id']: + if k in values and not isinstance(values[k], str) and values[k] is not None: + del values[k] + + return values - if values['id_random']: - return values['id_random'] - return None - - @validator('id', always=True) - def event_track_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['id_random']: - log.debug(values['id_random']) - return redis_lookup_id_random(record_id_random=values['id_random'], table_name='event_track') - return None - - @validator('event_id', always=True) - def event_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['event_id_random']: - return redis_lookup_id_random(record_id_random=values['event_id_random'], table_name='event') - return None - - @validator('event_location_id', always=True) - def event_location_id_lookup(cls, v, values, **kwargs): - log.setLevel(logging.WARNING) - log.debug(locals()) - - if values['event_location_id_random']: - return redis_lookup_id_random(record_id_random=values['event_location_id_random'], table_name='event_location') - return None + # 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', 'track_type', + 'event_name', 'event_start_datetime', 'event_end_datetime', + 'event_abstract_list', 'event_device_list', 'event_file_list', + 'event_presentation_list', 'event_presenter_list', 'event_session_list', 'event_track_list' + ] class Config: underscore_attrs_are_private = True - allow_population_by_field_name = True + allow_population_by_field_name = False fields = base_fields # ### END ### API Event Track Models ### Event_Track_Base() ### diff --git a/app/models/organization_models.py b/app/models/organization_models.py index 1834e47..79385b7 100644 --- a/app/models/organization_models.py +++ b/app/models/organization_models.py @@ -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, root_validator from app.db_sql import redis_lookup_id_random @@ -86,6 +86,11 @@ class Organization_Base(BaseModel): return values + # 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] = [ + 'contact' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False diff --git a/app/models/person_models.py b/app/models/person_models.py index 5dcc912..3217daf 100644 --- a/app/models/person_models.py +++ b/app/models/person_models.py @@ -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, root_validator from app.db_sql import redis_lookup_id_random @@ -184,6 +184,19 @@ class Person_Base(BaseModel): return True return v + # 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] = [ + 'membership_person_id', 'first_last_name', 'first_middle_last_name', + 'last_first_name', 'last_first_middle_name', 'informal_full_name', + 'professional_full_name', 'lu_gender_name', 'email', 'cc_email', + 'username', 'user_name', 'user_email', 'user_allow_auth_key', + 'user_super', 'user_manager', 'user_administrator', 'user_public', + 'event_list', 'hosted_file_list', 'journal_list', 'contact', + 'membership_person', 'membership_group_list', 'membership_type_list', + 'orders_info', 'order_list', 'order_cart', 'order_cart_v3', + 'organization', 'post_list', 'user' + ] + class Config: underscore_attrs_are_private = True allow_population_by_field_name = False