Машинный перевод под контролем человека
Этот контент переведён с помощью машинной генерации, направляемой составленными людьми глоссариями и руководствами по стилю. Поскольку текст не проверяется вручную построчно, возможны отдельные ошибки или неестественные формулировки.
В случае любых расхождений авторитетным источником считается оригинальная версия на английском языке.
Интеграция с MongoEngine
MongoEngine представляет документы MongoDB в виде синхронных классов Python с использованием API полей в стиле Django. Модуль starlette_admin.contrib.mongoengine предоставляет специализированные классы Admin и ModelView, которые строят административные представления непосредственно на основе ваших определений mongoengine.Document.
Ключевые возможности:
- Автоматическое преобразование типов полей, связей и встроенных документов.
- Поддержка загрузки файлов на основе GridFS через
FileFieldиImageFieldиз коробки.
Установка
Минимальный пример
Вы должны установить соединение с MongoDB до того, как любой запрос достигнет административного интерфейса. Лучший способ гарантировать выполнение этого условия — обернуть логику подключения внутри контекстного менеджера lifespan вашего основного приложения.
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)
Конструктор ModelView принимает класс mongoengine.Document напрямую. Список полей, формы и фильтры автоматически формируются на основе полей документа.
Основные классы: Admin и ModelView
Класс mongoengine.Admin
Класс mongoengine.Admin расширяет базовый Admin, добавляя специализированный маршрут: /api/file/{db}/{col}/{pk}. Этот маршрут передаёт файл GridFS из браузера напрямую.
Поскольку каждая загрузка через FileField и ImageField в модели MongoEngine сохраняется в GridFS, этот маршрут необходим для отдачи таких файлов. Всегда используйте mongoengine.Admin вместо базового Admin.
Класс mongoengine.ModelView
В отличие от базового класса, конструктор mongoengine.ModelView принимает позиционный аргумент document вместо декларативного класса модели:
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,
):
Если атрибут fields не задан в вашем подклассе ModelView, по умолчанию включаются все поля документа в порядке их объявления.
Атрибуты key, menu_label и display_name подчиняются строгому порядку определения значений:
- Аргумент конструктора.
- Атрибут уровня класса, заданный в подклассе.
- Значение, вычисляемое на основе имени класса документа (
keyстановится именем после слагификации,menu_label— плюрализованным «причёсанным» именем, аdisplay_name— единичным «причёсанным» именем).
from starlette_admin.contrib.mongoengine import ModelView
class CategoryView(ModelView):
fields = ["id", "name"]
searchable_fields = ["name"]
Реестр фильтров
Для каждого типа поля предусмотрен фиксированный набор фильтров, предоставляемых реестром MongoEngineFilterRegistry. Эти значения по умолчанию можно переопределить для отдельного поля с помощью аргумента filters=[...].
| Тип поля | Доступные фильтры |
|---|---|
StringField |
contains, not contains, starts with, ends with, equals, not equals, is null, is not null |
TextAreaField |
contains, not contains, starts with, ends with, is null, is not null |
EnumField |
equals, not equals, in, not in, is null, is not null |
NumberField |
equals, not equals, greater than, less than, between, is null, is not null |
FloatField |
equals, not equals, greater than, less than, between, is null, is not null |
DateField |
equals, between, in the past, in the future, is null, is not null |
DateTimeField |
equals, between, in the past, in the future, is null, is not null |
BooleanField |
is true, is false, is null, is not null |
TagsField |
in, not in, is null, is not null |
RelationField |
is null, is not null |
ObjectIdField |
equals, not equals, in, not in, is null, is not null |
Note
ObjectIdField соответствует полю id документа.
Под капотом метод apply() каждого фильтра возвращает фрагмент Q MongoEngine для своего конкретного условия. Вложенные деревья FilterGroup затем комбинируют эти фрагменты с помощью битовых операторов (& или |) перед выполнением запроса. Подробнее см. документацию Filters.
Встроенные документы
Поле EmbeddedDocumentField в MongoEngine преобразуется в CollectionField. Этот процесс рекурсивно преобразует каждое поле встроенного документа в его собственное подполе:
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))
В этом примере:
- Поле
addressотображается как вложенная подформа при создании и редактировании и как вложенный блок на странице детального просмотра. - Поле
comments(экземплярEmbeddedDocumentListField) преобразуется вListFieldизCollectionField. Оно отображается как повторяющаяся группа подформ — по одной для каждой записи списка.
Полный рабочий пример
В этом разделе представлен полный готовый к запуску пример интеграции MongoEngine со starlette-admin.
1. Установите зависимости
Пакет fastapi[standard] включает FastAPI CLI, что позволяет запустить сервер разработки командой fastapi dev.
2. Создайте приложение
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. Запустите сервер
Запустите сервер разработки FastAPI:
Откройте в браузере страницу http://127.0.0.1:8000/admin, чтобы просмотреть административную панель и работать с ней.
Расширенный пример: приложение
examples/16-mongoengineв репозитории содержит полнофункциональный пример. Оно включает инлайн-представления (inline views), события (events), пользовательские действия над строками и пакетные действия, а также загрузку изображений и файлов через GridFS.
Что читать дальше
- Views: ознакомьтесь с параметрами конфигурации
BaseModelView, не зависящими от backend. - Fields: подробное руководство по каждому типу поля и его атрибутам, включая
CollectionField. - Filters: изучите интерфейс конструктора фильтров и узнайте, как написать собственный фильтр.
- Beanie: откройте для себя асинхронную альтернативу для MongoDB на основе Pydantic.