Skip to main content

Muffin-Admin

Tests PyPI Python versions

An admin interface for Muffin applications.

Muffin-Admin

It mounts a react-admin single page app on top of Muffin-Rest resources, so a resource that already has a REST API gets list, create, edit and delete screens without writing any JavaScript.

Features

  • Resources for Peewee ORM and SQLAlchemy Core through Muffin-Rest
  • Filtering, sorting and pagination for list views
  • Custom actions, dashboard cards and authorization hooks

Requirements

  • Python >= 3.11 (tested on 3.11, 3.12, 3.13, 3.14 and 3.15)
  • Muffin >= 3.0
  • Muffin-Rest >= 14.2

Muffin 3 keeps handler routes as (paths, methods, hosts) tuples and Muffin-Rest 14.2 follows it; older releases are not supported.

Installation

pip install muffin-admin

With SQLAlchemy Core support:

pip install muffin-admin[sqlalchemy]

With Peewee ORM support:

pip install muffin-admin[peewee]

Usage

Initialize the admin:

from muffin_admin import Plugin

admin = Plugin(**options)

Initialize admin handlers (example for Peewee ORM):

from muffin_admin import PWAdminHandler


@admin.route
class UserResource(PWAdminHandler):
    """Create Admin Resource for the User model."""

    class Meta(PWAdminHandler.Meta):
        """Tune the resource."""

        # Peewee Model for the admin resource
        model = User

        # Filters
        filters = "email", "created", "is_active", "role"

        # Tune serialization/deserialization schemas
        schema_meta = {
            "load_only": ("password",),
            "dump_only": ("created",),
        }

        # Columns to show
        columns = "id", "email", "is_active", "role", "created"

        # Custom Material-UI icon
        icon = "People"

Connect admin to a Muffin application:

admin.setup(app, **options)

More examples live in the example directory of the repository.

Authentication

Decorate an authentication function with admin.check_auth:

@admin.check_auth
async def auth(request):
    """Fake authorization method. Just checks for an auth token exists in request."""
    return request.headers.get("authorization")

Register a function to return user's information:

@admin.get_identity
async def ident(request):
    """Get current user information. Just an example."""
    user_id = request.headers.get("authorization")
    user = User.select().where(User.id == user_id).first()
    if user:
        return {"id": user.id, "fullName": user.email}

Implement a login handler for the standard react-admin auth page:

@admin.login
async def login(request):
    """Login a user."""
    data = await request.data()
    user = (
        User.select()
        .where(User.email == data["username"], User.password == data["password"])
        .first()
    )
    return ResponseJSON(user and user.id)

Dashboard

Decorate a function with admin.dashboard to fill the admin start page:

@admin.dashboard
async def dashboard(request):
    """Render dashboard cards."""
    return [
        [
            {"title": "App config", "value": [(key, str(value)) for key, value in app.cfg]},
            {"title": "Request headers", "value": dict(request.headers)},
        ],
    ]

A list of blocks is rendered as a row of cards. A value given as a list of lists is rendered as a table, any other value as JSON.

Custom actions

An action is a handler method decorated with AdminHandler.action (or with the ORM specific subclass). The admin renders a button for every decorated method:

from muffin_admin import PWAdminHandler


@admin.route
class UserResource(PWAdminHandler):
    class Meta(PWAdminHandler.Meta):
        model = User

    @PWAdminHandler.action("/user/disable", label="Disable Users", view="bulk")
    async def disable_users(self, request, resource=None):
        """Mark selected users as inactive."""
        ids = request.query.getall("ids")
        await User.update(is_active=False).where(User.email << ids)
        return {"status": True, "ids": ids}

    @PWAdminHandler.action("/user/{id}/admin", view="show")
    async def mark_admin(self, request, resource=None):
        ...

The decorator accepts the following arguments:

Argument Description
paths One or more URL paths for the action
methods HTTP methods allowed for the route, by default any method
hosts A host name (or a list of names) to bind the route to
view Where to show the button: list, show or bulk
icon Material-UI icon name
label Button label, the humanized method name by default
schema Marshmallow schema; the admin renders a form and passes the validated data as the data argument
help A link to an action help page
confirm Ask for confirmation before the request, either True or a message
file Serve the response as a file download (list and show views only)

Any other keyword argument is passed to react-admin as an action property.

Restrict an action to an HTTP method and a domain:

@PWAdminHandler.action("/user/greet", methods=("POST",), hosts="example.com", view="list")
async def greet(self, request, resource=None):
    ...

An action with a schema receives the validated payload:

@PWAdminHandler.action(
    "/user/greet",
    "/user/{id}/greet",
    label="Greeter",
    view=["list", "show"],
    schema=GreetSchema,
)
async def greet(self, request, resource=None, data=None):
    return {"status": True, "message": f"Hello {data.name}"}

Configuration options

Option Default value Description
prefix "/admin" Admin's HTTP URL prefix
title "Muffin-Admin" Admin's title
main_js_url "{prefix}/main.js" A link to main JS file
custom_js_url "" A link to custom JS file
custom_css_url "" A link to custom CSS file
login_url None An HTTP URL for your custom login page
logout_url None An HTTP URL for your custom logout page
menu_sort True Sort menu items
auth_storage "localstorage" Where to keep authorization information (localstorage|cookies)
auth_storage_name "muffin_admin_auth" Localstorage/Cookie name for authentication info
app_bar_links [{"url": "/", "icon": "Home", "title": "Home"}] Appbar links
mutation_mode "optimistic" React-Admin edit mutation mode (pessimistic|optimistic|undoable)
help None A link to the admin help page
locales None Translations for react-admin, merged with the handler locales

Bug tracker

If you have any suggestions, bug reports or annoyances please report them to the issue tracker at https://github.com/klen/muffin-admin/issues

Contributing

Development of Muffin-Admin happens at https://github.com/klen/muffin-admin

Contributors:

License

Licensed under a MIT license.

Metadata

Release files for muffin-admin 13.3.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 muffin-admin 13.3.0
File Size Uploaded Provenance
muffin_admin-13.3.0.tar.gz 1.1 MB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for muffin-admin 13.3.0
File Interpreter ABI Platform
muffin_admin-13.3.0-py3-none-any.whl Python 3 none any Details

Total release size: 2.3 MB

Release files / muffin_admin-13.3.0.tar.gz

Download URL muffin_admin-13.3.0.tar.gz
Size 1.1 MB
Tags Source
SHA-256 checksum
How to use checksums
1a27c2234a56ca4c6bed22914c9cfd4feeda6b35be33d5ebbac05d9d3e741324
BLAKE2b-256 checksum
How to use checksums
656a66909afe3b4c70a272bbedbeb6a2fdd5260afdb5a43758129b7c81566812
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Release files / muffin_admin-13.3.0-py3-none-any.whl

Download URL muffin_admin-13.3.0-py3-none-any.whl
Size 1.1 MB
Tags Python 3
SHA-256 checksum
How to use checksums
3815c078fbfc002cb37fbf02ae788c456b6e33eaa6b4589a4654d88131024d66
BLAKE2b-256 checksum
How to use checksums
ad05a536d4a5be574432ecf9270df720e30067baee77490f1f858642c917abdd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via uv/0.13.1 {"installer":{"name":"uv","version":"0.13.1","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

Security for muffin-admin 13.3.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.

Release history Release notifications | RSS feed

This release

13.3.0 This release

2 release files No provenance

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