1

I have a FastAPI project using SQLModel as the orm. I would like to use multiple different databases in the same project. For example I would like one FastAPI endpoint to query 1 database and another FastAPI endpoint to query a completely different database. However I'm struggling to find any documentation on how to go about doing so. I'm assuming it involves a particular setup of the SQLModel classes/engines along with the metadata but I'm unsure. Any direction at all would be appreciated. Thanks.

configure.ng
  • 159
  • 1
  • 11

1 Answers1

0

Querying a database is done via a Session instance. That session object is instantiated by providing the database Engine object, which you typically get by calling the create_engine constructor. That constructor takes the database URI as its first argument. I see no problem just setting up two different engines like this:

engine_a = create_engine("sqlite:///a.db", echo=True)
engine_b = create_engine("sqlite:///b.db", echo=True)

If you want to have the same tables in both databases, you can just issue the create_all call for both engines:

SQLModel.metadata.create_all(engine_a)
SQLModel.metadata.create_all(engine_b)

If you actually want your databases to house different tables, you should probably take care in setting up your migration logic appropriately. I assume for a serious project, you'll be using something like alembic for that. But for a quick test, you can even issue individual CREATE TABLE statements depending on your needs. Say you want model A to map only to the database connected to via engine_a, then you could do this:

A.__table__.create(engine_a)

For querying you can use the session context just the same as always, but pass the correct engine to it:

with Session(engine_a) as session:
    ...

Here is a full working example:

from typing import Optional

from sqlmodel import Field, Session, SQLModel, create_engine


class A(SQLModel, table=True):
    id: Optional[int] = Field(primary_key=True)
    foo: str


class B(SQLModel, table=True):
    id: Optional[int] = Field(primary_key=True)
    bar: str


if __name__ == '__main__':
    engine_a = create_engine("sqlite:///a.db", echo=True)
    engine_b = create_engine("sqlite:///b.db", echo=True)

    A.__table__.create(engine_a)
    B.__table__.create(engine_b)

    with Session(engine_a) as session:
        session.add(A(foo="abc"))
        session.commit()

    with Session(engine_b) as session:
        session.add(B(bar="xyz"))
        session.commit()

You can open the resulting a.db and b.db in something like sqlitebrowser to see that table A with its entry were actually created only in a.db, whereas table B with its entry are only in b.db.

Hope this helps.

Daniil Fajnberg
  • 12,753
  • 2
  • 10
  • 41
  • Thanks a lot. This really helps. I'm just getting started with this whole SQLModel/FastAPI ecosystem. I know alembic is for helping with migrations, but could you expand a bit on how that might help this particular case of wanting to have one fastapi project where I have different endpoints hitting different DBs depending on what they are doing? Thanks. – configure.ng Oct 03 '22 at 14:42