SQLAdmin: a SQLAlchemy admin for FastAPI and Starlette
SQLAlchemy Admin for FastAPI and Starlette
At a glance
- What is it?
- SQLAdmin mounts a Tabler-based admin interface onto an existing FastAPI or Starlette app and builds its CRUD screens from SQLAlchemy models. It is a good fit for teams already using SQLAlchemy 2.0 who want an internal back office without a second service.
- Who is it for?
- Adopt SQLAdmin if your application already runs on Starlette or FastAPI and your data layer is SQLAlchemy 2.0 or SQLModel, because the admin is mounted on the same app and reuses the same engine. Do not adopt it if you need a standalone admin service that manages several unrelated databases, or if you cannot accept that the project describes itself as Beta in its classifiers.
- Can I use it commercially?
- Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 9 days ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 24, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Who SQLAdmin is for, and the problem it removes
Every application with a database eventually needs a screen where a support person can look up a record, correct a typo, or deactivate an account. Building that screen by hand means writing list pages, detail pages, forms, validation and pagination for each table, and then rewriting all of it whenever a column changes. SQLAdmin takes the position that the model definitions you already have are enough to generate those screens.
The intended user is a Python developer running a Starlette or FastAPI service on SQLAlchemy 2.0. The README lists sync and async engines, Starlette integration, FastAPI integration, WTForms for form building, SQLModel support, and a Tabler-based UI. That combination is the point: the admin is mounted inside the application you already deploy, so it inherits your process, your configuration and your database engine instead of becoming a second service with its own credentials and its own deployment.
It is not a general-purpose database browser. It is a model-driven admin, which means anything it shows you must first exist as a mapped class. If you want to poke at arbitrary tables in a database you did not model, this is the wrong tool.
How the Admin object, ModelView and WTForms fit together
The mechanism is a small number of cooperating pieces. You construct an Admin with your ASGI application and a SQLAlchemy engine. You then subclass ModelView, bind it to a model with the model= keyword, and register it with admin.add_view(). Each registered view becomes a set of routes under the admin mount point, and the README states that visiting /admin in the browser shows the interface.
Forms are not generated by SQLAlchemy alone. WTForms is a direct dependency in pyproject.toml, so the form layer is WTForms, and ModelView class attributes such as column_list decide which fields appear in the list screen. That is why the configuration surface looks like class-level declarations rather than a schema file: you are configuring a view class, not describing a table.
The dependency list also tells you what the project is built on. Starlette is pinned to >=0.50,<2.0.0, WTForms to >=3.1,<3.3, and SQLAlchemy to >= 2.0. Python 3.10 through 3.14 are listed as supported. Those upper bounds are worth reading before you upgrade anything else in your stack: a Starlette 2.0 release would fall outside the declared range.
Installing SQLAdmin and adding a first ModelView
The README gives pip as the installation route, with optional extras for authentication and internationalization. The auth extra installs itsdangerous and enables session-backed authentication; the i18n extra installs babel and enables internationalization and localization; full installs both.
pip install sqladmin
pip install "sqladmin[auth]"
pip install "sqladmin[full]"The README's quickstart defines a declarative model and an engine, then creates the tables. Note the connect_args in the example, which the README includes for SQLite because of thread handling.
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import declarative_base
Base = declarative_base()
engine = create_engine(
"sqlite:///example.db",
connect_args={"check_same_thread": False},
)
class User(Base):
__tablename__ = "users"
id = Column(Integer, primary_key=True)
name = Column(String)
Base.metadata.create_all(engine)Attaching the admin to FastAPI takes three lines beyond the imports. The Admin is constructed with the app and the engine, and the view is registered on the admin instance.
from fastapi import FastAPI
from sqladmin import Admin, ModelView
app = FastAPI()
admin = Admin(app, engine)
class UserAdmin(ModelView, model=User):
column_list = [User.id, User.name]
admin.add_view(UserAdmin)For Starlette the shape is identical, with Starlette() substituted for FastAPI(). After starting your server, the README says visiting /admin shows the SQLAdmin interface. The project also hosts a live demo at sqladmin-demo.vercel.app/admin with the credentials superadmin and superadmin, which is the fastest way to see the screens before writing any code.
Where the boundaries are: Beta status, version ranges and scope
The first limitation is stated by the project itself. The classifiers in pyproject.toml include Development Status :: 4 - Beta. That is not a marketing hedge, it is the maintainers' own label, and it should set expectations about API stability across minor releases.
The second is the dependency envelope. Starlette is constrained below 2.0.0 and WTForms below 3.3. If your application pins a Starlette version outside that window, or if you depend on a WTForms 3.3 feature, SQLAdmin will not install cleanly alongside it. This is a real constraint for large applications with their own pinning policies, and it is the kind of thing that surfaces during a lockfile update rather than at first install.
The third boundary is scope. The README describes an admin interface for SQLAlchemy models. It does not describe a workflow engine, an audit log, a permissions matrix, or row-level access rules. Authentication is listed as an extra that installs itsdangerous for session-backed authentication, and the README points to the documentation for it. What that authentication does and does not cover is a documentation question, and the README does not answer it. If your requirement is per-object authorization, assume you are building it on top.
Finally, the repository does not document rollback anywhere in the README. If you need a supported downgrade path between versions, that is something to establish from the changelog and release history rather than from the front page.
SQLAdmin compared with Starlette-Admin, FastAPI-Admin and Flask-Admin
The README names three related projects, and the differences are structural rather than cosmetic.
Flask-Admin is the acknowledged inspiration, and the README says most features and configurations are implemented the same way. The difference is the framework underneath: Flask-Admin is a WSGI application tied to Flask, while SQLAdmin is built for ASGI frameworks and lists asgi and asyncio among its topics. If your application is Flask, SQLAdmin is not a candidate at all.
FastAPI-Admin is an admin interface for FastAPI that works with TortoiseORM. The split is the ORM, not the web framework. Choosing between them is really choosing between SQLAlchemy and TortoiseORM, and if your models are already SQLAlchemy declarative classes, SQLAdmin reuses them while a Tortoise ORM admin would require a second set of model definitions.
Dashboard is an admin interface for ASGI frameworks that works with the orm package. Again the dividing line is the data layer. SQLAdmin's position is that SQLAlchemy 2.0, including async engines and SQLModel, is the thing you already have, so the admin should be generated from it rather than from a parallel schema. The trade-off is that SQLAdmin inherits SQLAlchemy's configuration model, which is more verbose than a schema-first admin but far more familiar to a team already writing mapped classes.
Maintenance, releases and what upgrading costs
The repository is not archived, and the last push was on 2026-09-20. Release 0.32.0 is dated the same day, 0.31.1 on 2026-09-01, and 0.31.0 on 2026-08-06. Three releases in roughly seven weeks, with the most recent landing on the same day as the last push, indicates a project that ships frequently and keeps the repository current.
Frequent minor releases have a cost, though. The version history shows the jump from 0.31 to 0.32 in a single step, and the Beta classifier means you should read CHANGELOG.md before each upgrade rather than assuming a patch-level bump. The practical upgrade procedure is visible in the Makefile: uv sync --all-groups installs the development dependency groups, and uv run coverage run -a --concurrency=thread,greenlet -m pytest runs the suite. If you want to check a candidate version against the project's own tests before adopting it, those are the commands the maintainers use.
The licence is BSD-3-Clause, declared both in pyproject.toml and in the LICENSE.md file at the repository root. That is a permissive licence, and it is the same family used by Starlette and FastAPI. Whether it fits your organisation's policy on attribution and redistribution is a question for your legal team, not something this article can settle.
One more operational detail from the Makefile: the project maintains translation catalogs under sqladmin/translations using pybabel, with targets for extracting strings, initialising a new locale, and compiling .mo files. If you run SQLAdmin in a non-English deployment, that directory is where the shipped translations live and where a new locale would be added.
Editorial conclusion
Adopt SQLAdmin if your application already runs on Starlette or FastAPI and your data layer is SQLAlchemy 2.0 or SQLModel, because the admin is mounted on the same app and reuses the same engine. Do not adopt it if you need a standalone admin service that manages several unrelated databases, or if you cannot accept that the project describes itself as Beta in its classifiers. Before committing, verify three things against your own codebase: that the Starlette and WTForms version ranges in pyproject.toml resolve with your lockfile, that your session authentication story works with the auth extra, and that the ModelView configuration you need is actually documented rather than assumed.
Frequently asked questions
Is there an admin panel available for FastAPI?
SQLAdmin is one: the README shows constructing Admin(app, engine) on a FastAPI instance and registering a ModelView subclass, after which /admin serves the interface. The same code works with Starlette by swapping the application class.
What is SQLAdmin in Python?
It is a SQLAlchemy admin interface for Starlette and FastAPI, distributed on PyPI as sqladmin and licensed BSD-3-Clause. It builds CRUD screens from your mapped models using WTForms and renders them with Tabler.
What are the alternatives to SQLAdmin?
The README names Flask-Admin, which inspired it and targets Flask on WSGI, FastAPI-Admin, which works with TortoiseORM, and Dashboard, which works with the orm package on ASGI. The main difference is which ORM and framework each one assumes.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/smithyhq-sqladmin)