Skip to main content

LiteAdmin

PyPI Python License: MIT

Django Admin–style admin panel for Litestar and FastAPI, with Tortoise ORM and SQLAlchemy.

React UI ships in litedmin/static/ — no npm needed for normal use.

Install

pip install litedmin
pip install "litedmin[fastapi,sqlalchemy]"   # FastAPI + SQLAlchemy
pip install "litedmin[litestar,tortoise]"    # Litestar + Tortoise
pip install "litedmin[all]"                  # both ORMs + frameworks + dev tools

Core symbols (AdminConfig, OrmSettings, register, ModelAdmin) import without ORM/framework extras. ORM and web stacks load only when you import their modules (or touch lazy attributes on litedmin).

From source (examples / development)

git clone https://github.com/ggb0yyyyyyy/litedmin.git
cd litedmin
pip install -e ".[litestar,tortoise]"      # examples/tortoise (port 8000)
pip install -e ".[litestar,sqlalchemy]"    # examples/sqlalchemy (port 8011)
pip install -e ".[fastapi,tortoise]"
pip install -e ".[all]"

Repository layout

liteDmin/
  litedmin/                 installable package
    backend/
      core/                 AdminSite, config, OrmSettings, decorators
      admin/                ModelAdmin, changelist, formsets, permissions
      api/                  AdminAPI / endpoints
      auth/                 session, backends, UserAdminMixin, system models
      orm/                  Tortoise / SQLAlchemy backends + repositories
      integration/          Litestar & FastAPI Admin mounts, DI helpers
      dto/ storage/
    static/                 bundled React UI
  frontend/                 React sources (rebuild → litedmin/static/)
  examples/                 Litestar + Tortoise / SQLAlchemy demos
  tests/

Quick start (Litestar + Tortoise)

Superuser is not created on app startup. Create it once via CLI, then run the example:

# optional credentials for CLI
export ADMIN_USERNAME=admin
export ADMIN_PASSWORD=admin

py -3.11 -m litedmin createsuperuser --settings examples.tortoise.settings:orm_settings
py -3.11 -m uvicorn examples.tortoise.app:app --host 0.0.0.0 --port 8000

Open http://localhost:8000/admin

SQLAlchemy example: same flow with examples.sqlalchemy.settings:orm_settings and port 8011. Details: examples/README.md, examples/CREDENTIALS.md.

Minimal wiring

from litestar import Litestar, get

# Shared Starlette Admin ASGI app; Litestar/FastAPI only provide mount helpers.
from litedmin.backend.integration.litestar import Admin
from litedmin.backend.integration import init_tortoise_with_litedmin, close_tortoise
# FastAPI: from litedmin.backend.integration.fastapi import Admin
#      or: from litedmin import Admin
# Then: app.mount(admin.prefix, admin.as_asgi_app())

from examples.tortoise.admin_config import ExampleAdminConfig
from examples.tortoise.settings import AUTO_DISCOVER_MODULES, orm_settings

admin = Admin(
    prefix='/admin',
    config=ExampleAdminConfig(),          # AdminConfig: theme / UI / auth_user_model
    auto_discover_modules=AUTO_DISCOVER_MODULES,
)

async def on_startup():
    await init_tortoise_with_litedmin(orm_settings)  # OrmSettings: ORM + DB
    await admin.ensure_started()  # validate admin + sync permissions (no user seed)

async def on_shutdown():
    await close_tortoise()

@get('/')
async def root() -> dict:
    return {'admin': '/admin'}

app = Litestar(
    route_handlers=[root, admin.as_mount()],
    on_startup=[on_startup],
    on_shutdown=[on_shutdown],
)

File / rich-text media storage

Pass any StorageBackend (save / delete / url) into Admin(storage=...). Rich editor uploads go to POST /admin/media/upload and embed the returned url in HTML.

Examples use LocalFileStorage + /media static route — see examples/README.md. Swap in S3/MinIO by implementing the same protocol in your app.

SQLAlchemy apps also call admin.configure_sqlalchemy(...) after init_sqlalchemy_with_litedmin_async — see examples/sqlalchemy/app.py.

ModelAdmin

  • Prefer TortoiseModelAdmin / SQLAlchemyModelAdmin (repository save/delete).
  • Register with @register / AdminSite.register — admin_site is always injected; do not construct ModelAdmin without a site.
  • Permission / persist hooks are async (has_*, get_permissions, get_list_scope_filters, save_model, delete_model, process_extra_fields). Sync getters (get_list_display, …) stay sync.
  • Users with password field: UserAdminMixin.
  • Long readonly textareas: pass options on the widget itself (SPA preview + “Show full text” dialog):
from litedmin import Textarea

class AnalysisAdmin(SQLAlchemyModelAdmin):
    widgets = {
        'error': Textarea(collapse_chars=280),
    }

Field references (SQLAlchemy)

Settings accept plain names ('title', 'author__username') for any ORM. For SQLAlchemy you can also pass the model's own attributes (and Link(...) for relation paths), so a type checker catches a misspelt field:

from litedmin import Link, action, display, register
from litedmin.backend.orm.sqlalchemy import SQLAlchemyModelAdmin

@register(Post)
class PostAdmin(SQLAlchemyModelAdmin):
    list_display = [Post.id, Post.title, Link(Post.author, User.username), 'title_upper']
    search_fields = [Post.title, Link(Post.author, User.email)]
    ordering = [Post.created_at.desc()]
    list_filter = [Post.published, Post.status]

Tortoise models have no field attributes on the class — keep using strings there ('title', 'author__username'). Computed @display columns are always strings.

Tortoise example

from litedmin import action, register, display
from litedmin.backend.orm.tortoise import TortoiseModelAdmin

@action(description='Publish selected', row=True)
async def make_published(modeladmin, request, objects):
    # ``objects`` is a list of instances (not an ORM queryset)
    ...
    # Optional: return a status string for the SPA toast (e.g. background job accepted)
    # return 'Export queued'

@action(description='Refresh cache', toolbar=True, bulk=False, row=False)
async def refresh_cache(modeladmin, request, objects):
    # Page toolbar button (no selection); same POST /{model}/action with ids=[]
    ...
    return 'Refresh queued'

@register(Post)
class PostAdmin(TortoiseModelAdmin):
    list_display = ['title', 'title_upper']
    actions = [make_published, refresh_cache]  # each entry must use @action

    @display(label='Upper title')
    def title_upper(self, obj):
        return obj.title.upper()

    async def has_export_permission(self, request=None, obj=None):
        return True

List actions require @action (Django @admin.action style). Use row=True for per-row buttons; bulk=False to hide from the bulk dropdown; toolbar=True for page-level tools above the list (always empty selection). Signature is always (modeladmin, request, objects).

Auth

  • Default: session cookie login (SessionAuthBackend + SessionAuth).
  • SSO (Keycloak gateway handoff): GatewayWebAuthBackend — see examples/tortoise/app_gateway_web.py and examples/README.md.

CLI

litedmin createsuperuser --settings examples.tortoise.settings:orm_settings
# or
python -m litedmin createsuperuser --settings module.path:orm_settings

--username / --password / --email, or ADMIN_USERNAME / ADMIN_PASSWORD / ADMIN_EMAIL.

Config split

Object Role
AdminConfig Theme, UI, sidebar groups, optional auth_user_model
OrmSettings orm_type, database URL, app modules for ORM init

Features

  • @register / AdminSite.register ModelAdmin API
  • SQLAlchemy field attributes / Link(...) in ModelAdmin settings (strings for Tortoise)
  • @display computed list columns
  • @action list actions (bulk dropdown + optional row=True buttons)
  • CSV/JSON export (has_export_permission)
  • Django-like permissions, groups, LogEntry audit trail
  • list_editable, date_hierarchy, bulk actions, inlines
  • Row-level scope via get_list_scope_filters + object-level has_*
  • Double-submit CSRF cookie for session auth (AdminConfig.csrf_protect)
  • StorageBackend protocol for file uploads

Typing

Package is typed; project mypy config is in pyproject.toml ([tool.mypy]).

pip install -e ".[dev]"
python -m mypy litedmin

Change the React UI

pip install -e ".[all]"
# or: pip install -r requirements-dev.txt
bash scripts/build_frontend.sh
git add litedmin/static/

License

MIT

Metadata

Release files for litedmin 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for litedmin 0.4.0
File Size Uploaded Provenance Actions
litedmin-0.4.0.tar.gz 2.5 MB Without provenance Details for litedmin-0.4.0.tar.gz

Built distribution (wheel)

Table of built distributions (wheels) for litedmin 0.4.0
File Interpreter ABI Platform Actions
litedmin-0.4.0-py3-none-any.whl Python 3 none any Details for litedmin-0.4.0-py3-none-any.whl

Total release size: 5.1 MB

Release files / litedmin-0.4.0.tar.gz

Download URL litedmin-0.4.0.tar.gz
Size 2.5 MB
Tags Source
SHA-256 checksum
How to use checksums
54ba72b08548dcd02cdb1f637b74c5680ec91cd8e856aec9d10d4fac05d4e5e9
BLAKE2b-256 checksum
How to use checksums
4ef9744c02933ec7e78fcd4f57ffa21f59c926eac49e525727c353a4beb0f1c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Release files / litedmin-0.4.0-py3-none-any.whl

Download URL litedmin-0.4.0-py3-none-any.whl
Size 2.6 MB
Tags Python 3
SHA-256 checksum
How to use checksums
d45ecfbfdd43b9270cc008317dd8a5b95753231020bfc3f33d7f9df6f68ffa69
BLAKE2b-256 checksum
How to use checksums
4467f22bc2de9e36163fc31378765b32d544e4eee8d39ca77ae2fa74e141df10
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.14.4

Security for litedmin 0.4.0

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page