Home
Softono

Oxyde Admin

Open source MIT Python
39
Stars
0
Forks
2
Issues
0
Watchers
3 months
Last Commit

 About Oxyde Admin

Oxyde Admin Auto-generated admin panel for Oxyde ORM with zero boilerplate.

Platforms

Web Self-hosted

Languages

Python

Links

Need Help Installing Oxyde Admin?

We provide expert installation service for this software. Our team will install, configure, and secure Oxyde Admin on your server. plans start at just $30.

Oxyde Admin

View on GitHub

Logo

Oxyde Admin Auto-generated admin panel for Oxyde ORM with zero boilerplate.

PyPI Downloads


Features

  • Automatic CRUD - list, create, edit, delete from your Oxyde models
  • Search & filters - text search across fields, column filters (FK, bool, string)
  • Foreign key handling - select dropdowns with inline create dialog
  • Many-to-many relations - multi-select widget with junction-table sync
  • Enum & array fields - Enum columns rendered as dropdowns, list[T] as array editors
  • Streaming export - CSV / JSON export of large tables in chunks, with row caps
  • Bulk operations - bulk delete and update from the list view
  • Authentication - pluggable sync/async callback, JWT-ready
  • Theming - 3 presets, 17 colors, 8 surface palettes
  • Multi-framework - FastAPI, Litestar, Sanic, Quart and Falcon adapters

oxyde-admin list view

Requirements

  • Python ≥ 3.10
  • oxyde ≥ 0.5.0
  • One of the supported frameworks (fastapi / litestar / sanic / quart / falcon)
  • An ASGI server (e.g. uvicorn, hypercorn)

Installation

pip install oxyde-admin

Quick start

from fastapi import FastAPI
from oxyde import db
from oxyde_admin import FastAPIAdmin

from models import User, Post, Comment

admin = FastAPIAdmin(title="My Admin")
admin.register(User, list_display=["name", "email"], search_fields=["name", "email"])
admin.register(Post, list_display=["title", "is_published"], list_filter=["is_published"])
admin.register(Comment)

app = FastAPI(lifespan=db.lifespan(default="sqlite:///app.db"))
app.mount("/admin", admin.app)

Open http://localhost:8000/admin/ and get a full CRUD interface for your models. The admin ships its own SPA frontend, so no separate frontend build is required — the static assets are served by the same mount.

edit form

Configuration

All adapters accept the same constructor parameters:

Parameter Default Description
title "Oxyde Admin" Title shown in the UI
prefix "/admin" URL prefix (FastAPI / Sanic / Quart / Falcon; on Litestar set the path via mount)
preset Preset.AURA PrimeVue preset
primary_color PrimaryColor.SKY Accent color
surface Surface.SLATE Surface palette
per_page 100 Maximum page size for the list view
export_chunk_size 10_000 Rows per chunk while streaming an export
max_export_rows 100_000 Hard cap on total exported rows
auth_check None Callable (request) -> bool, sync or async
login_url None Where the UI redirects on 401

Frameworks

FastAPI

from oxyde_admin import FastAPIAdmin

admin = FastAPIAdmin(title="My Admin")
# register models...
app.mount("/admin", admin.app)

Litestar

from litestar import Litestar, asgi
from oxyde_admin import LitestarAdmin

admin = LitestarAdmin(title="My Admin")
# register models...

app = Litestar(
    route_handlers=[
        asgi(path="/admin", is_mount=True)(admin.app),
    ],
)

Sanic

from sanic import Sanic
from oxyde_admin import SanicAdmin

admin = SanicAdmin(title="My Admin", prefix="/admin")
# register models...

app = Sanic("MyApp")
admin.register_exception_handlers(app)
app.blueprint(admin.blueprint)

Quart

from quart import Quart
from oxyde_admin import QuartAdmin

admin = QuartAdmin(title="My Admin", prefix="/admin")
# register models...

app = Quart(__name__)
admin.init_app(app)

Falcon

import falcon.asgi
from oxyde_admin import FalconAdmin

admin = FalconAdmin(title="My Admin", prefix="/admin")
# register models...

app = falcon.asgi.App()
admin.init_app(app)

Model registration

admin.register(
    Post,
    list_display=["title", "author_id", "is_published", "views"],
    search_fields=["title", "content"],
    list_filter=["author_id", "is_published"],
    readonly_fields=["views"],
    ordering=["-views"],
    display_field="title",
    column_labels={"author_id": "Author", "is_published": "Published"},
    exportable=True,
    group="Content",
    icon="pi pi-file-edit",
)
Parameter Description
list_display Columns shown in the list view
search_fields Fields included in text search
list_filter Columns available as filters
readonly_fields Fields disabled in the edit form
ordering Default sort order (prefix - for descending)
display_field Field used as label in FK dropdowns
column_labels Custom column headers
exportable Enable CSV/JSON export (default: True)
group Sidebar group name
icon Sidebar icon (PrimeIcons)

You can also auto-register all models at once:

admin.register_all()

# or exclude specific models
admin.register_all(exclude={InternalModel})

Field types

The admin reads field metadata from _db_meta and renders an appropriate widget:

Type Widget
str / int / float Text / number input
bool Toggle
date / datetime Date / datetime picker
UUID Text input
Enum Dropdown with the enum members
list[T] Array editor (chips for primitive item types)
Foreign key Searchable dropdown with inline create dialog
Many-to-many Multi-select; junction rows synced on save

Tip: Foreign-key and M2M target models must also be registered. Use display_field on the target model to control the label shown in dropdowns; otherwise the first string field (or the primary key) is used.

Theming

from oxyde_admin import Preset, PrimaryColor, Surface

admin = FastAPIAdmin(
    title="My Admin",
    preset=Preset.AURA,
    primary_color=PrimaryColor.TEAL,
    surface=Surface.ZINC,
)

themes

Presets: AURA, LARA, NORA

Colors: NOIR EMERALD GREEN LIME ORANGE AMBER YELLOW TEAL CYAN SKY BLUE INDIGO VIOLET PURPLE FUCHSIA PINK ROSE

Surfaces: SLATE GRAY ZINC NEUTRAL STONE SOHO VIVA OCEAN

Authentication

Note: This section describes the current behavior. The authentication flow will be reworked in the future.

Pass an auth_check callback and a login_url:

async def check_admin(request) -> bool:
    token = request.headers.get("Authorization", "").removeprefix("Bearer ")
    return await verify_admin_token(token)

admin = FastAPIAdmin(
    auth_check=check_admin,
    login_url="/auth/login",
)
  • auth_check may be sync or async — the adapter detects this at runtime.
  • GET <prefix>/api/config is intentionally not gated by auth_check so the unauthenticated UI can read login_url and the theme on the login screen.
  • The frontend stores the token in localStorage under the key admin_token and sends it as Authorization: Bearer <token> on every API request. On a 401 it clears the token and redirects to login_url.

Your login_url endpoint must accept POST {"email": "...", "password": "..."} and return {"token": "<...>"} on success, or a non-2xx response with {"detail": "..."} on failure.

API

The admin UI talks to the backend through the following endpoints (relative to the admin prefix):

GET    /api/config
GET    /api/models
GET    /api/models/counts
GET    /api/<model>/schema
GET    /api/<model>?page=&per_page=&ordering=&search=&<filter>=
POST   /api/<model>
GET    /api/<model>/<pk>
PATCH  /api/<model>/<pk>
DELETE /api/<model>/<pk>
GET    /api/<model>/options?search=&limit=&include=
GET    /api/<model>/export?format=csv|json&ids=&ordering=&search=
POST   /api/<model>/bulk-delete   { "ids": [...] }
POST   /api/<model>/bulk-update   { "ids": [...], "data": {...} }

<model> is the table name (e.g. users, not User). Schema responses include x-db-* extensions (primary key, FK target, nullable, default, db type, max length, enum members, array item type, M2M target / through) that you can use to drive a custom UI — see oxyde_admin/schema.py for the full list.

Examples

Working applications with auth, fixtures, FK / M2M relations, and enum / array fields are in examples/ for each supported framework (FastAPI, Litestar, Sanic, Quart, Falcon).

License

This project is licensed under the terms of the MIT license.