Skip to main content

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 registry — site.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 MongoDB — mode="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

Metadata

Release files for fastapi-mongo-admin 2.0.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for fastapi-mongo-admin 2.0.2
File Size Uploaded
fastapi_mongo_admin-2.0.2.tar.gz 527.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for fastapi-mongo-admin 2.0.2
File Interpreter ABI Platform
fastapi_mongo_admin-2.0.2-py3-none-any.whl Python 3 none any Details

Total release size: 1.1 MB

Release files / fastapi_mongo_admin-2.0.2.tar.gz

Download URL fastapi_mongo_admin-2.0.2.tar.gz
Size 527.6 kB
Tags Source
SHA-256 checksum
How to use checksums
cf5dbfa7e5d855ad373482c6d711eb2bf69d59a2d2f7e15893586427926756f7
BLAKE2b-256 checksum
How to use checksums
df77e69409200793b19a721c8336e615fdb04bba5206b0113794d0addfa723d2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.11

Release files / fastapi_mongo_admin-2.0.2-py3-none-any.whl

Download URL fastapi_mongo_admin-2.0.2-py3-none-any.whl
Size 537.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
9d94e34c68f3f8385b3c24548e0fd19ecf5d9ebf6874b3957778e28402da9400
BLAKE2b-256 checksum
How to use checksums
469d7c41fb06b57248a717a4fac796285fee3d655d0ce31264f78132d4ef66c9
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.11

Release history Release notifications | RSS feed

This release

2.0.2 This release

2 release files

2.0.1

2 release files

2.0.0

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.6

2 release files

0.0.5

2 release files

0.0.4

2 release files

0.0.3

2 release files

0.0.2

2 release files

0.0.1

2 release files

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