I am building a multilingual api for an educational app using fastapi.
I have created differrent tables for translated parts and created mysql views for differrent languages.
I did not want to write differrent pydantic classes for each translated table parts.
Instead I wrote sone functions to manipulate sqlalchemy _tablename_ attribute of sqlachemy tables. This way I thought I could reach differrent tables like lessons_en or lessons_de which are just mysql views for translated parts. Table structure and view structure matches the original sqlalchemy model and pydantic schema.
e.g.
def get_table_suffix():
lang = sys_vars.CURRENT_LOCAL__LANG
print(str(lang) + "from get_table_suffix")
match lang:
case "":
return ""
case "en":
return "_en"
case "de":
return "_de"
def get_localized_table_name(tbl_nm: str):
table_name = tbl_nm + get_table_suffix()
return table_name
then..
class LessonSummary(Base):
__tablename__ = get_localized_table_name("lessons")
for matching correct language view then at login function I call ..
settings: dict = get_user_settings(user)
set_user_lang(settings)
sys_vars.CURRENT_LOCAL__LANG = sys_vars.LOCAL_LANGUAGES[settings["language"]]
these functions set CURRENT_LOCAL__LANG which happens ( I tested it ) But since the tables are loaded, changing tablename does not change tables.
def get_user_settings(user: schemas.User):
settings: dict = {}
for setting in user.Settings:
settings[setting.SettingName] = setting.SettingValue
return settings
def set_user_lang(settings: dict):
sys_vars.CURRENT_LOCAL__LANG = sys_vars.LOCAL_LANGUAGES[settings["language"]]
print(sys_vars.CURRENT_LOCAL__LANG + " from set_user_lang")
return sys_vars.CURRENT_LOCAL__LANG
However, _tablename_ attribute is set at loading time and I cannot seem to change it at run time. I tried to do it before the app loaded routers but user login happens after app startup and I need to reach the instance of the table. I tried MetaData() obj but no-luck
So, my question.. Am I going the wrong way about this problem? Can I dynamically change the _tablename_ at run time and reflect the changes in session. Do I need a reload somehow? I did manage to store language correctly inside jwt but I can't change the tablename. So How can I change it at runtime?
I tried changing the tablename dynamically but sine the app had already loaded I was not successful.
You can use imperative mapping style instead of declarative style. With imperative style your model classes are not linked to metadata until you link them by calling
mapper_registry.map_imperatively()
.But in this case there are some duplication (you have to declare fields twice - in model and in table).
Output: