from ship_kit.admin import setup_admin_routes
from ship_kit.admin_routes import admin_dashboard, admin_detail, admin_bulk_delete
from fasthtml.common import *
from dataclasses import dataclass
from typing import Optional
= fast_app()
app, rt = Database('app.db')
db
# Define your models
@dataclass
class Product:
str
name: float
price: id: Optional[int] = None
@dataclass
class User:
str
username: str
email: id: Optional[int] = None
# Create tables
= db.create(Product, pk='id')
products = db.create(User, pk='id')
users
# Your models list
= [
models 'products', products, Product),
('users', users, User)
(
]
# 1. Basic CRUD (already exists)
for name, table, model in models:
setup_admin_routes(rt, name, table, model)
# 2. Add dashboard
admin_dashboard(rt, models)
# 3. Add detail views (only if needed)
for name, table, model in models:
admin_detail(rt, name, table, model)
# 4. Add bulk delete (only if needed)
for name, table, model in models:
admin_bulk_delete(rt, name, table)
admin_routes
Extended admin routes for dashboards and bulk operations
Admin Dashboard
A simple dashboard showing all managed models with counts and links.
admin_dashboard
admin_dashboard (rt, models, path='/admin')
*Simple dashboard showing all models.
Args: rt: FastHTML route object models: List of tuples (name, table, model_class) path: Dashboard path (default: ‘/admin’)*
Detail Views
Read-only detail views for individual items.
admin_detail
admin_detail (rt, name, table, model_class)
*Show single item details.
Args: rt: FastHTML route object name: Model name (e.g., ‘product’) table: Database table model_class: Dataclass model*
Bulk Operations
Delete multiple items at once.
admin_bulk_delete
admin_bulk_delete (rt, name, table)
*Delete multiple items at once.
Args: rt: FastHTML route object name: Model name (e.g., ‘product’) table: Database table*
Usage Example
Here’s how to use these admin route extensions with your existing admin setup:
Interactive Demo
Let’s create a demo showing the dashboard in action:
from fasthtml.common import *
from fasthtml.jupyter import JupyUvi
from monsterui.all import *
from dataclasses import dataclass
from typing import Optional
# Demo setup
= fast_app(hdrs=Theme.blue.headers())
demo_app, demo_rt = Database(":memory:")
demo_db
@dataclass
class DemoProduct:
str
name: float
price: id: Optional[int] = None
@dataclass
class DemoUser:
str
username: str
email: id: Optional[int] = None
# Create tables
= demo_db.create(DemoProduct, pk='id')
demo_products = demo_db.create(DemoUser, pk='id')
demo_users
# Add sample data
="Widget", price=19.99)
demo_products.insert(name="Gadget", price=29.99)
demo_products.insert(name="alice", email="alice@example.com")
demo_users.insert(username="bob", email="bob@example.com")
demo_users.insert(username
# Mock auth for demo - override the imported require_role
import ship_kit.permissions
= lambda role, req, sess: True
ship_kit.permissions.require_role
# Import admin functions
from ship_kit.admin import setup_admin_routes
from ship_kit.admin_routes import admin_dashboard, admin_detail
# Set up models
= [
models 'products', demo_products, DemoProduct),
('users', demo_users, DemoUser)
(
]
# Add basic CRUD routes first
for name, table, model in models:
setup_admin_routes(demo_rt, name, table, model)
# Add dashboard
admin_dashboard(demo_rt, models)
# Add detail views
for name, table, model in models:
admin_detail(demo_rt, name, table, model)
# Add a home route that redirects to admin
@demo_rt('/')
def home():
return RedirectResponse('/admin', status_code=303)
# Start the demo server
print("Starting admin demo server...")
print("\nDemo routes:")
print("- http://localhost:8000/admin - Admin Dashboard")
print("- http://localhost:8000/admin/products/ - Products List")
print("- http://localhost:8000/admin/users/ - Users List")
= JupyUvi(demo_app) server
Starting admin demo server...
Demo routes:
- http://localhost:8000/admin - Admin Dashboard
- http://localhost:8000/admin/products/ - Products List
- http://localhost:8000/admin/users/ - Users List
# Remember to stop the server when done to avoid dangling threads
server.stop()