Skip to main content

Django-inspired server-rendered admin for FastAPI and MongoDB

Project description

FastAPI Mongo Admin

A Django-inspired, server-rendered admin framework for FastAPI and MongoDB.

v2.0.0 replaces the legacy React SPA with a Jinja2 + HTMX admin interface, a full ModelAdmin configuration API, pluggable authentication, and support for both async (Motor) and sync (PyMongo) MongoDB backends.

Screenshots

Customer changelist

Customer change form

Key Features

  • Django-like registrysite.register(Model, AdminClass)
  • Server-rendered admin UI — changelist, add/change forms, delete confirmation, bulk actions
  • List filters — choice, boolean, date, related, and custom ListFilter classes
  • Pydantic-driven forms — validation and schema inference from your models
  • Field mapping — map model fields to different MongoDB keys
  • Pluggable auth — wire any FastAPI Depends authentication/authorization
  • Sync + async MongoDBmode="async" (Motor) or mode="sync" (PyMongo)
  • Customization — template overrides, ModelAdmin hooks, custom admin views
  • JSON API/admin/api/{collection}/ for programmatic access (read-only by default; optional write methods for /docs)

Breaking Changes (v0.x → v2)

  • React UI and /admin-ui mount removed; admin lives at /admin
  • MongoAdmin alias removed; use AdminSite or site
  • Built-in demo token auth removed; provide auth_dependency
  • Legacy /admin/collections/.../documents routes removed

Installation

# Using uv (recommended)
uv add fastapi-mongo-admin

# Or pip
pip install fastapi-mongo-admin

Quick Start

1. Define models and admin classes

from pydantic import BaseModel
from fastapi_mongo_admin import ModelAdmin, site, display, action
from fastapi_mongo_admin.admin.filters import ChoiceListFilter, DateFieldListFilter


class Product(BaseModel):
    name: str
    price: float
    category: str
    active: bool = True


class ProductAdmin(ModelAdmin):
    model = Product
    collection_name = "products"
    list_display = ["name", "category", "price", "active"]
    list_filter = ["category", "active"]
    search_fields = ["name", "category"]
    list_per_page = 25
    choices = {
        "category": [("books", "Books"), ("electronics", "Electronics")],
    }

    @display(description="Name")
    def name_upper(self, obj: dict) -> str:
        return str(obj.get("name", "")).upper()

    @action("Deactivate selected")
    async def deactivate_selected(self, request, queryset: list[dict]) -> None:
        pass


site.register(Product, ProductAdmin)

2. Mount in FastAPI (async)

from fastapi import FastAPI
from motor.motor_asyncio import AsyncIOMotorClient
from fastapi_mongo_admin import mount_admin_app

app = FastAPI()
client = AsyncIOMotorClient("mongodb://localhost:27017")
database = client["my_db"]


async def get_database():
    return database


mount_admin_app(app, get_database, admin_site=site, mode="async")

3. Sync MongoDB

from pymongo import MongoClient
from fastapi_mongo_admin import mount_admin_app

client = MongoClient("mongodb://localhost:27017")
db = client["my_db"]

mount_admin_app(app, lambda: db, admin_site=site, mode="sync")

Visit http://localhost:8000/admin/ for the admin index.

Authentication

Pass any FastAPI-compatible dependency:

from fastapi import Depends, HTTPException


async def get_admin_user():
  # Your JWT/session validation here
  return {"id": "user-1", "is_staff": True}


mount_admin_app(
    app,
    get_database,
    admin_site=site,
    auth_dependency=get_admin_user,
)

JSON API

Read endpoints are always available at /admin/api/{collection}/. By default only GET operations appear in OpenAPI (/docs).

Enable POST, PUT, PATCH, and DELETE routes (and Swagger documentation):

mount_admin_app(
    app,
    get_database,
    admin_site=site,
    auth_dependency=get_admin_user,
    api_write_methods=True,
)
Method URL Description
GET /admin/api/{collection}/ Paginated list (page, q)
GET /admin/api/{collection}/{id} Single document
POST /admin/api/{collection}/ Create (when api_write_methods=True)
PUT /admin/api/{collection}/{id} Update
PATCH /admin/api/{collection}/{id} Partial update
DELETE /admin/api/{collection}/{id} Delete

Write requests use the same Pydantic validation and ModelAdmin permission hooks as the HTML admin.

Override per-model permissions on ModelAdmin:

class ProductAdmin(ModelAdmin):
    def has_add_permission(self, request, user=None) -> bool:
        return bool(user and user.get("is_staff"))

ModelAdmin Options

Option Description
model Pydantic model for validation
collection_name MongoDB collection (required)
list_display Changelist columns (fields or @display methods)
list_display_links Clickable columns
list_filter Field names or ListFilter subclasses
search_fields Text search fields
list_per_page Pagination size (default 25)
ordering Default sort, e.g. ["-created_at"]
date_hierarchy Date drill-down field
list_select_related {"field": "collection"} for related lookups
fieldsets Grouped change form layout
readonly_fields Non-editable fields
field_mapping Model field → DB field mapping
actions Bulk action method names
choices Choice lookups for filters/forms
date_format Display format for date fields (default: 8 Apr 2026)
datetime_format Display format for datetime fields (default: 8 Apr 2026, 7:32pm)

Date and Time Display

date and datetime fields are formatted automatically on changelists and readonly form fields. Form inputs still use ISO values for HTML date/datetime pickers.

Default formats:

  • Date: 8 Apr 2026
  • Datetime: 8 Apr 2026, 7:32pm

Customize per model:

class OrderAdmin(ModelAdmin):
    date_format = "j M Y"                  # Django-style tokens
    datetime_format = "%d/%m/%Y %H:%M"     # or standard strftime

Override completely:

def format_datetime_value(self, value) -> str:
    return my_formatter(value)

Template Customization

from pathlib import Path

site = AdminSite(template_dirs=[Path("myapp/templates")])

class ProductAdmin(ModelAdmin):
    change_list_template = "myapp/admin/product_change_list.html"

Register custom views:

async def reports(request):
    return {"report": "data"}

site.register_view("Reports", "/reports/", reports)

URL Scheme

URL View
GET /admin/ Admin index
GET /admin/{collection}/ Changelist
GET /admin/{collection}/add/ Add form
GET/POST /admin/{collection}/{id}/change/ Change form
POST /admin/{collection}/{id}/delete/ Delete
POST /admin/{collection}/action/ Bulk actions
GET /admin/api/{collection}/ JSON list API
GET /admin/api/{collection}/{id} JSON detail API
POST/PUT/PATCH/DELETE /admin/api/... JSON write API (api_write_methods=True)

Development

make install   # uv sync --group dev
make test      # pytest
make lint      # ruff
make secure    # bandit + pysentry-rs
make docs      # build Sphinx HTML docs
make help      # list all targets

License

MIT

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

fastapi_mongo_admin-2.0.1.tar.gz (527.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

fastapi_mongo_admin-2.0.1-py3-none-any.whl (100.2 kB view details)

Uploaded Python 3

File details

Details for the file fastapi_mongo_admin-2.0.1.tar.gz.

File metadata

  • Download URL: fastapi_mongo_admin-2.0.1.tar.gz
  • Upload date:
  • Size: 527.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.11

File hashes

Hashes for fastapi_mongo_admin-2.0.1.tar.gz
Algorithm Hash digest
SHA256 ba38eadab40105fdf3b215ee3b1508b44cb53dd5fb05c7a81cbb53a81c28c798
MD5 a046f0a80cbe82a6acc264a8db06712c
BLAKE2b-256 bb7109bd594e98e6cd80bdd14013e69843a566a32ae72386e04010f73e6f91c0

See more details on using hashes here.

File details

Details for the file fastapi_mongo_admin-2.0.1-py3-none-any.whl.

File metadata

File hashes

Hashes for fastapi_mongo_admin-2.0.1-py3-none-any.whl
Algorithm Hash digest
SHA256 59b7d6da6330628f8f50e716e22c3c9205dc04135ec3ff2939ced6703560a276
MD5 24bde42571c996170522635468bfb454
BLAKE2b-256 32b56f6db6e1b83df0efe34df0e9ecddae038f176d75558e83cc4f30c2491eac

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page