Aller au contenu
Traduction automatique supervisée

Ce contenu est traduit à l'aide d'une génération automatique guidée par des glossaires et des guides de style élaborés par des humains. Le texte n'étant pas relu manuellement ligne par ligne, des erreurs ou des tournures maladroites peuvent occasionnellement apparaître.

En cas de divergence, la version anglaise constitue la source de référence.

Lire la version originale en anglais

Intégration de MongoEngine

MongoEngine modélise les documents MongoDB sous forme de classes Python synchrones en s'appuyant sur une API de champs de style Django. Le module starlette_admin.contrib.mongoengine fournit des classes Admin et ModelView spécialisées qui construisent directement les vues d'administration à partir de vos définitions mongoengine.Document.

Fonctionnalités clés :

  • Conversion automatique des types de champs, des relations et des documents intégrés.
  • Prise en charge prête à l'emploi des téléversements FileField et ImageField adossés à GridFS.

Installation

pip install starlette-admin mongoengine
uv install starlette-admin mongoengine

Exemple minimal

Vous devez établir la connexion à MongoDB avant que la moindre requête n'atteigne l'interface d'administration. Pour garantir que ce prérequis soit satisfait, la meilleure approche consiste à encapsuler la logique de connexion dans le gestionnaire de contexte lifespan de votre application principale.

from contextlib import asynccontextmanager

import mongoengine as me
from starlette.applications import Starlette
from starlette_admin.contrib.mongoengine import Admin, ModelView


class Category(me.Document):
    name = me.StringField(required=True, min_length=2, max_length=50)

    meta = {"collection": "categories"}


@asynccontextmanager
async def lifespan(app: Starlette):
    me.connect(db="podcast_admin", host="mongodb://localhost:27017")
    yield
    me.disconnect()


app = Starlette(lifespan=lifespan)

admin = Admin(title="Podcast Admin", secret_key="change-me-in-production")
admin.add_view(ModelView(Category, icon="fa fa-tags"))
admin.mount_to(app)

Le ModelView accepte directement la classe mongoengine.Document. Il déduit automatiquement la liste des champs, les formulaires et les filtres à partir des champs du document.

Classes principales : Admin et ModelView

La classe mongoengine.Admin

La classe mongoengine.Admin étend la classe Admin de base en ajoutant une route spécialisée : /api/file/{db}/{col}/{pk}. Cette route renvoie directement un fichier GridFS au navigateur sous forme de flux.

Comme chaque téléversement via un champ FileField ou ImageField d'un modèle MongoEngine est stocké dans GridFS, cette route est indispensable pour servir ces fichiers. Utilisez toujours mongoengine.Admin plutôt que la classe Admin de base.

La classe mongoengine.ModelView

Contrairement à la classe de base, le constructeur du mongoengine.ModelView prend un argument positionnel document au lieu d'une classe de modèle déclarative :

def __init__(
    self,
    document: type[me.Document],
    icon: str | None = None,
    display_name: str | None = None,
    menu_label: str | None = None,
    key: str | None = None,
    converter: BaseMongoEngineModelConverter | None = None,
):

Si vous laissez l'attribut fields non défini dans votre sous-classe de ModelView, il inclut par défaut tous les champs du document, dans leur ordre de déclaration.

Les attributs tels que key, menu_label et display_name suivent un ordre de repli strict :

  1. L'argument du constructeur.
  2. Un attribut défini au niveau de la classe dans la sous-classe.
  3. Une valeur dérivée du nom de classe du document (key devient le nom slugifié, menu_label devient le nom pluralisé et embelli, et display_name devient le nom singulier embelli).
from starlette_admin.contrib.mongoengine import ModelView


class CategoryView(ModelView):
    fields = ["id", "name"]
    searchable_fields = ["name"]

Registre de filtres

Chaque type de champ inclut un ensemble fixe de filtres fourni par le MongoEngineFilterRegistry. Vous pouvez remplacer ces valeurs par défaut champ par champ grâce à l'argument filters=[...].

Type de champ Filtres disponibles
StringField contient, ne contient pas, commence par, se termine par, égal à, différent de, est nul, n'est pas nul
TextAreaField contient, ne contient pas, commence par, se termine par, est nul, n'est pas nul
EnumField égal à, différent de, dans, pas dans, est nul, n'est pas nul
NumberField égal à, différent de, supérieur à, inférieur à, compris entre, est nul, n'est pas nul
FloatField égal à, différent de, supérieur à, inférieur à, compris entre, est nul, n'est pas nul
DateField égal à, compris entre, dans le passé, dans le futur, est nul, n'est pas nul
DateTimeField égal à, compris entre, dans le passé, dans le futur, est nul, n'est pas nul
BooleanField est vrai, est faux, est nul, n'est pas nul
TagsField dans, pas dans, est nul, n'est pas nul
RelationField est nul, n'est pas nul
ObjectIdField égal à, différent de, dans, pas dans, est nul, n'est pas nul

Note

Le champ ObjectIdField représente l'id du document.

En coulisses, la méthode apply() de chaque filtre renvoie un fragment Q de MongoEngine correspondant à sa condition spécifique. Les arbres de FilterGroup imbriqués combinent ensuite ces fragments à l'aide d'opérateurs bit à bit (& ou |) avant d'exécuter la requête. Pour plus de détails, consultez la documentation Filters.

Documents intégrés

Le champ EmbeddedDocumentField de MongoEngine est converti en CollectionField. Ce processus convertit récursivement chaque champ du document intégré en son propre sous-champ :

import mongoengine as me
from starlette_admin.contrib.mongoengine import Admin, ModelView


class Address(me.EmbeddedDocument):
    street = me.StringField()
    city = me.StringField()


class Comment(me.EmbeddedDocument):
    content = me.StringField()


class Post(me.Document):
    name = me.StringField()
    address = me.EmbeddedDocumentField(Address)
    comments = me.EmbeddedDocumentListField(Comment)


class PostView(ModelView):
    fields = ["id", "name", "address", "comments"]


admin = Admin()
admin.add_view(PostView(Post))

Dans cet exemple :

  • Le champ address s'affiche sous la forme d'un sous-formulaire imbriqué lors de la création et de la modification, et sous la forme d'un bloc imbriqué sur la page de détail.
  • Le champ comments (un EmbeddedDocumentListField) est converti en ListField de CollectionField. Il s'affiche sous la forme d'un groupe répétable de sous-formulaires, avec un affichage par entrée de la liste.

Exemple complet et fonctionnel

Cette section fournit une intégration MongoEngine complète et exécutable avec starlette-admin.

1. Installer les dépendances

pip install starlette-admin mongoengine "fastapi[standard]"
uv install starlette-admin mongoengine "fastapi[standard]"

Le paquet fastapi[standard] inclut la CLI FastAPI, ce qui vous permet de démarrer le serveur de développement en exécutant fastapi dev.

2. Créer l'application

main.py
from contextlib import asynccontextmanager
from datetime import datetime, timezone
from enum import Enum

import mongoengine as me
from fastapi import FastAPI
from starlette.requests import Request
from starlette_admin import SlugField
from starlette_admin.contrib.mongoengine import Admin, ModelView

MONGO_URI = "mongodb://localhost:27017"


class PostStatus(str, Enum):
    DRAFT = "DRAFT"
    PUBLISHED = "PUBLISHED"
    ARCHIVED = "ARCHIVED"


class Author(me.Document):
    name = me.StringField(required=True)

    def __admin_repr__(self, request: Request) -> str:
        return self.name

    meta = {"collection": "authors"}


class Post(me.Document):
    title = me.StringField(required=True)
    slug = me.StringField(required=True, unique=True)
    content = me.StringField(required=True)
    status = me.EnumField(PostStatus, default=PostStatus.DRAFT)
    created_at = me.DateTimeField(default=lambda: datetime.now(timezone.utc))
    author = me.ReferenceField(Author, required=True)

    def __admin_repr__(self, request: Request) -> str:
        return self.title

    meta = {"collection": "posts"}


class AuthorView(ModelView):
    fields = ["id", "name"]


class PostView(ModelView):
    fields = [
        "id",
        "title",
        SlugField("slug", populate_from="title"),
        "content",
        "status",
        "created_at",
        "author",
    ]
    exclude_fields_from_create = ["created_at"]
    exclude_fields_from_edit = ["created_at"]
    searchable_fields = ["title", "content", "status"]
    fields_default_sort = [("created_at", True)]


@asynccontextmanager
async def lifespan(app: FastAPI):
    me.connect(db="blog", host=MONGO_URI)
    yield
    me.disconnect()


app = FastAPI(lifespan=lifespan)

admin = Admin(title="Blog Admin", secret_key="change-me")
admin.add_view(AuthorView(Author, icon="fa fa-user"))
admin.add_view(PostView(Post, icon="fa fa-newspaper"))
admin.mount_to(app)

3. Lancer le serveur

Démarrez le serveur de développement FastAPI :

fastapi dev
uv run -- fastapi dev

Rendez-vous à l'adresse http://127.0.0.1:8000/admin dans votre navigateur pour consulter le tableau de bord d'administration et interagir avec lui.

Exemple avancé : examples/16-mongoengine dans le dépôt contient une application complète. Elle inclut des vues en ligne, des événements ainsi que des actions personnalisées sur les lignes et par lot, et des téléversements d'images et de fichiers via GridFS.


Pour aller plus loin

  • Views : explorez les options de configuration de BaseModelView, indépendantes du backend.
  • Fields : guide détaillé de chaque type de champ et de ses attributs, y compris le CollectionField.
  • Filters : explorez l'interface du générateur de filtres et apprenez à écrire un filtre personnalisé.
  • Beanie : découvrez l'alternative asynchrone fondée sur Pydantic pour MongoDB.