Build an internal admin panel in Python
Most admin panels are the same shape: find a user, an order or an account, then do something to it. Make them an admin, change their plan, refund the order. With Callables, you build that from plain Python functions. No front end, no admin framework.
Step 1: the actions
Start with the things your team needs to do. Each one is an ordinary function:
from typing import Literal
from callables import Group, Next
users = Group("users", title="Users", secrets=["DATABASE_URL"])
@users.deploy(title="Make admin")
def make_admin(user_id: int) -> str:
"""Gives the user admin access."""
...
return f"User {user_id} is now an admin."
@users.deploy(title="Change plan")
def set_plan(
user_id: int,
plan: Literal["Free", "Pro", "Enterprise"],
) -> str:
"""Moves the user to another plan."""
...
Putting them in a Group shows them together as one section in the web app, and shares the database secret. See groups.
Step 2: a search that leads to them
Now add the search, and list what can be done with each result in next:
@users.deploy(
title="Find user",
next=[make_admin, Next(set_plan, label="Change plan", user_id="id")],
)
def search(query: str) -> list[dict]:
"""Finds users by name or email."""
return [{
"id": 42,
"user_id": 42,
"name": "Ann Lee",
"email": "[email protected]",
}]
Someone on your support team opens Find user, types "ann", and gets a table. Each row has a Make admin button and a Change plan button. Clicking one opens that action's form with the user filled in from the row, so all they pick is the new plan.
How inputs get filled in
- An action's inputs are filled from result fields with the same name.
make_admintakesuser_id, and each row has auser_id, so it's filled automatically. - When the names differ, map them:
Next(set_plan, user_id="id")fillsuser_idfrom the row'sid. label=changes the button text.- Anything the row doesn't fill, the person chooses in the form.
Every step stands alone
Each action is still a normal function. People can run Change plan directly if they already know the user ID, schedule it, or be given access to it separately. And every run links back to the search it came from, so the history shows the whole path: who searched, what they found, and what they did.
People only see the actions they're allowed to run. You might let the whole support team search, but only a few people make admins. See permissions.
It works in the terminal too
The same flow runs from your own terminal. call users search --query ann lists the rows, asks which one and what to do next, then prompts for the remaining inputs. Handy for the engineers on the team.
Ideas
- Orders: find an order, then refund it, resend the receipt or change the address.
- Accounts: find a company, then extend its trial or change its seat count.
- Content: find a post, then unpublish it or transfer it to another author.
Turn your scripts into tools your team can run
Add @deploy to a Python function and push. Your team gets a form, schedules and run history.