1

FastAPI Routing Question:

Hi, I've got 3 databases set up (master databases that is, postgres instances) as such:

 master1: - db1: - tables... - db2: - and so on... - db3: master2: - db1: - db2: - db3: master3: - db1: - db2: - db3: 

all managed with Alembic so they'll all be the same, but I'll add error handling. But, all the databases in each instance actually have the same name, its not like master1_db1 = 'abc' and master2_db1 = 'def', they're both actually db1 for all intents and purposes.

I want to expose endpoints as follows: /{master_i}/{db_j}/{tables_xyz}

so they can visit /master1/db1/table1 but also switch to /master2/db1/table1 to get data from a different environment. (These are really just local, dev, and prod databases fwiw).

But the logic shouldn't change between the .../db1/table1 part, in fact, I want to strip the prefix {master_i} and only have the actual logic for /db1_table and then the variable {master_i} is a selector for what sql-alchemy engine I want to use.

So, my api is up and running at /db1/table1/ but I want the user to be at {master_i}/db1/table1 and strip off the master_i to send to sql-alchemy db-engine, and all logic to be the same at /db1/table1/.

So, when they visit {master_i}/db1/table1:

SQLAlchemy Engine get the {master_i} part

 def sql_engine(passed_db_name, server_port): db_url = URL.create( "postgresql+psycopg2", username = os.getenv('DB_USER'), password = os.getenv('DB_PASS'), host = '127.0.0.1', port = int(server_port), database = str(**master_i**) # <<< Where I am using the path prefix {master_i} ) return create_engine(db_url) 

and FastAPI gets the /db1/table1

 @db1_router.get('/table_1') def get_table_1(): return [{"get": "sql_alchemy_output_from_{master_i}_here"}] 

I just don't want 3 copies of the same FastAPI routers/endpoints/functions when they're not going to differ.

2
  • Does it have to be a path parameter? Could you achieve the same result using a query parameter with a sensible default? e.g. /table1?master=1&db=1. Also, I would suggest setting up all your database engines, and configuring SQLAlchemy to return you a session rather than creating a new engine on each request docs Commented May 1, 2024 at 2:18
  • I figured out something pretty cool, I'll post the answer later, but I did end up doing the latter part of your comment, thanks PGHE Commented May 1, 2024 at 17:13

1 Answer 1

0

You can use multiple decorators for the same function, like this:

@db1_router.get('/table_1') @db2_router.get('/table_1') @db3_router.get('/table_1') def get_table_1(): return [{"get": "sql_alchemy_output_from_{master_i}_here"}] 
Sign up to request clarification or add additional context in comments.

1 Comment

amazing! so simple... I'll see what I can get going, thank you Mark

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.