@@ -46,6 +46,215 @@ pip install "fastapi-viewsets[test]" # pytest, httpx, coverage, etc.
4646
4747For async SQLAlchemy you still need a driver such as ` aiosqlite ` , ` asyncpg ` , or ` aiomysql ` alongside your database URL.
4848
49+ ## Database connection examples
50+
51+ ` fastapi-viewsets ` doesn't bundle DB drivers — you pick them per stack.
52+ The table below maps each ORM to the install command, the driver(s)
53+ you need, and the URL shape for ** PostgreSQL** , ** MySQL** , and
54+ ** Microsoft SQL Server** .
55+
56+ | ORM | PostgreSQL | MySQL | MSSQL |
57+ | --- | --- | --- | --- |
58+ | ** SQLAlchemy (sync)** | ` psycopg[binary] ` or ` psycopg2-binary ` | ` pymysql ` or ` mysqlclient ` | ` pyodbc ` + ODBC Driver 17/18 |
59+ | ** SQLAlchemy (async)** | ` asyncpg ` | ` aiomysql ` or ` asyncmy ` | ` aioodbc ` + ODBC Driver 17/18 |
60+ | ** Tortoise ORM** | ` asyncpg ` (built-in) | ` aiomysql ` (built-in) | Not supported by Tortoise |
61+ | ** Peewee** | ` psycopg2-binary ` | ` pymysql ` or ` mysqlclient ` | Not supported by this adapter |
62+
63+ > The ` SQLAlchemyAdapter ` auto-converts a sync URL to its async
64+ > counterpart (` postgresql:// ` → ` postgresql+asyncpg:// ` ,
65+ > ` mysql:// ` → ` mysql+aiomysql:// ` , ` sqlite:/// ` →
66+ > ` sqlite+aiosqlite:/// ` ). For MSSQL you have to set the async URL
67+ > explicitly via ` SQLALCHEMY_ASYNC_DATABASE_URL ` . If the matching async
68+ > driver is not installed, ` SQLAlchemyAdapter ` falls back to sync-only
69+ > mode and ` get_async_session() ` raises a helpful ` RuntimeError `
70+ > (since v1.2.1).
71+
72+ The library reads database configuration from environment variables
73+ (loaded via ` python-dotenv ` from ` .env ` ). Pick the ORM with ` ORM_TYPE ` ,
74+ then set the URL with ` <ORM>_DATABASE_URL ` (or the generic
75+ ` DATABASE_URL ` ).
76+
77+ ### SQLAlchemy (sync and async)
78+
79+ ``` bash
80+ # PostgreSQL
81+ pip install " fastapi-viewsets[sqlalchemy]" " psycopg[binary]" asyncpg
82+
83+ # MySQL
84+ pip install " fastapi-viewsets[sqlalchemy]" pymysql aiomysql
85+
86+ # MSSQL (needs Microsoft ODBC Driver 17 or 18 on the host)
87+ pip install " fastapi-viewsets[sqlalchemy]" pyodbc aioodbc
88+ ```
89+
90+ Example ` .env ` (one block at a time):
91+
92+ ``` dotenv
93+ # --- PostgreSQL ---
94+ ORM_TYPE=sqlalchemy
95+ SQLALCHEMY_DATABASE_URL=postgresql+psycopg://user:pass@db.example.com:5432/app
96+ # Optional explicit async URL; otherwise auto-derived to postgresql+asyncpg://
97+ SQLALCHEMY_ASYNC_DATABASE_URL=postgresql+asyncpg://user:pass@db.example.com:5432/app
98+
99+ # --- MySQL ---
100+ ORM_TYPE=sqlalchemy
101+ SQLALCHEMY_DATABASE_URL=mysql+pymysql://user:pass@db.example.com:3306/app?charset=utf8mb4
102+ SQLALCHEMY_ASYNC_DATABASE_URL=mysql+aiomysql://user:pass@db.example.com:3306/app?charset=utf8mb4
103+
104+ # --- MSSQL ---
105+ ORM_TYPE=sqlalchemy
106+ # URL-encode the ODBC driver name ("+" instead of spaces).
107+ SQLALCHEMY_DATABASE_URL=mssql+pyodbc://user:pass@db.example.com:1433/app?driver=ODBC+Driver+18+for+SQL+Server&Encrypt=yes&TrustServerCertificate=no
108+ SQLALCHEMY_ASYNC_DATABASE_URL=mssql+aioodbc://user:pass@db.example.com:1433/app?driver=ODBC+Driver+18+for+SQL+Server&Encrypt=yes&TrustServerCertificate=no
109+ ```
110+
111+ Use ` BaseViewset ` for sync code or ` AsyncBaseViewset ` for async code
112+ (see the [ Async quickstart] ( #async-quickstart-sqlalchemy-2x--pydantic-v2 )
113+ below).
114+
115+ ### Tortoise ORM
116+
117+ Tortoise is async-only. The adapter takes a database URL plus a list
118+ of model modules to register on startup.
119+
120+ ``` bash
121+ # PostgreSQL
122+ pip install " fastapi-viewsets[tortoise]" # pulls in asyncpg
123+
124+ # MySQL
125+ pip install " fastapi-viewsets[tortoise]" aiomysql
126+ ```
127+
128+ ``` dotenv
129+ # --- PostgreSQL ---
130+ ORM_TYPE=tortoise
131+ TORTOISE_DATABASE_URL=postgres://user:pass@db.example.com:5432/app
132+ TORTOISE_MODELS=["app.models"]
133+ TORTOISE_APP_LABEL=models
134+
135+ # --- MySQL ---
136+ ORM_TYPE=tortoise
137+ TORTOISE_DATABASE_URL=mysql://user:pass@db.example.com:3306/app
138+ TORTOISE_MODELS=["app.models"]
139+ TORTOISE_APP_LABEL=models
140+ ```
141+
142+ ``` python
143+ from fastapi import FastAPI
144+ from tortoise import Tortoise
145+
146+ from fastapi_viewsets import AsyncBaseViewset
147+ from fastapi_viewsets.orm.factory import ORMFactory
148+
149+ app = FastAPI()
150+ adapter = ORMFactory.get_default_adapter() # built from the env vars above
151+
152+
153+ @app.on_event (" startup" )
154+ async def _init_tortoise () -> None :
155+ """ Open the Tortoise connection pool and create schema if needed.
156+
157+ The adapter also initializes Tortoise lazily on first DB call;
158+ doing it here gives you control over schema creation.
159+ """
160+ await Tortoise.init(
161+ db_url = adapter.database_url,
162+ modules = {adapter.app_label: adapter.models},
163+ )
164+ await Tortoise.generate_schemas(safe = True )
165+
166+
167+ @app.on_event (" shutdown" )
168+ async def _close_tortoise () -> None :
169+ """ Close the Tortoise connection pool."""
170+ await Tortoise.close_connections()
171+
172+
173+ # Define your Tortoise models in app/models.py and pass them to AsyncBaseViewset.
174+ # from app.models import Item
175+ # from app.schemas import ItemSchema
176+ # items = AsyncBaseViewset(
177+ # endpoint="/items",
178+ # model=Item,
179+ # response_model=ItemSchema,
180+ # db_session=adapter.get_async_session,
181+ # orm_adapter=adapter,
182+ # tags=["items"],
183+ # )
184+ # items.register(methods=["LIST", "GET", "POST", "PATCH", "DELETE"])
185+ # app.include_router(items)
186+ ```
187+
188+ > ** MSSQL is not supported by Tortoise ORM.** Use SQLAlchemy with
189+ > ` aioodbc ` for SQL Server.
190+
191+ ### Peewee
192+
193+ Peewee is sync-only. The adapter parses the URL and instantiates the
194+ right ` Database ` class.
195+
196+ ``` bash
197+ # PostgreSQL
198+ pip install " fastapi-viewsets[peewee]" psycopg2-binary
199+
200+ # MySQL
201+ pip install " fastapi-viewsets[peewee]" pymysql
202+ ```
203+
204+ ``` dotenv
205+ # --- PostgreSQL ---
206+ ORM_TYPE=peewee
207+ PEEWEE_DATABASE_URL=postgresql://user:pass@db.example.com:5432/app
208+
209+ # --- MySQL ---
210+ ORM_TYPE=peewee
211+ PEEWEE_DATABASE_URL=mysql://user:pass@db.example.com:3306/app
212+ ```
213+
214+ ``` python
215+ from fastapi import FastAPI
216+
217+ from fastapi_viewsets import BaseViewset
218+ from fastapi_viewsets.orm.factory import ORMFactory
219+
220+ app = FastAPI()
221+ adapter = ORMFactory.get_default_adapter() # built from the env vars above
222+
223+ # from app.models import Item # peewee.Model subclass
224+ # from app.schemas import ItemSchema # Pydantic v2 schema
225+ # items = BaseViewset(
226+ # endpoint="/items",
227+ # model=Item,
228+ # response_model=ItemSchema,
229+ # db_session=adapter.get_session,
230+ # orm_adapter=adapter,
231+ # tags=["items"],
232+ # )
233+ # items.register(methods=["LIST", "GET", "POST", "PATCH", "DELETE"])
234+ # app.include_router(items)
235+ ```
236+
237+ > ** MSSQL is not supported by this Peewee adapter** (the URL parser
238+ > only handles ` sqlite:/// ` , ` postgresql:// ` , ` postgres:// ` ,
239+ > ` mysql:// ` ). For SQL Server, use SQLAlchemy.
240+
241+ ### Building the adapter from code (no env vars)
242+
243+ When you don't want to rely on environment variables, instantiate the
244+ adapter directly and pass it to the viewset via ` orm_adapter= ` :
245+
246+ ``` python
247+ from fastapi_viewsets.orm.factory import ORMFactory
248+
249+ adapter = ORMFactory.create_adapter(
250+ " sqlalchemy" ,
251+ {
252+ " database_url" : " postgresql+psycopg://user:pass@db.example.com:5432/app" ,
253+ " async_database_url" : " postgresql+asyncpg://user:pass@db.example.com:5432/app" ,
254+ },
255+ )
256+ ```
257+
49258## Quickstart (SQLAlchemy, sync)
50259
51260Save as ` main.py ` in an empty folder and run ` python main.py ` or ` uvicorn main:app --reload ` .
0 commit comments