从 Django Admin 迁移
如果你熟悉 Django Admin,那么 starlette-admin 会让你感到似曾相识。两者都通过声明式的按模型配置生成管理界面,并且都支持内联编辑、批量动作和按请求权限。
差异在于结构层面。starlette-admin 可以运行在任何 ASGI 应用上,而不要求 Django;它支持多种 ORM,并允许你接入自己的认证方案,而不是强制使用内置的用户模型。
本指南将每一个主要的 ModelAdmin 概念映射到 starlette-admin 中的对应实现,并提供并排的代码示例。
心智模型
| Django Admin 概念 | starlette-admin 对应实现 |
|---|---|
AdminSite |
挂载到你的应用上的 Admin 实例 |
ModelAdmin |
ModelView 子类 |
admin.site.register(Model, ModelAdmin) |
admin.add_view(MyView(Model)) |
urlpatterns 中的 admin.site.urls |
admin.mount_to(app) |
| Django ORM | 通过 starlette_admin.contrib.* 支持的 SQLAlchemy、SQLModel、MongoEngine、Beanie 或 Tortoise ORM |
模型上的 __str__ |
__admin_repr__(self, request),异步且可感知请求 |
| 由模型字段推断的表单字段 | 由后端转换器推断的字段,可按字段自定义 |
注册模型
from starlette_admin.contrib.sqla import Admin, ModelView
class PostView(ModelView):
fields = ["id", "title", "content", "published", "created_at"]
exclude_fields_from_list = ["content"]
searchable_fields = ["title", "content"]
admin = Admin(engine, title="Blog Admin", secret_key="change-me")
admin.add_view(PostView(Post, icon="fa fa-newspaper"))
admin.mount_to(app) # app is your FastAPI or Starlette instance
两个结构性差异尤为突出:
- 一份字段列表驱动所有页面。
fields是唯一事实来源。随后使用exclude_fields_from_list、exclude_fields_from_detail、exclude_fields_from_create和exclude_fields_from_edit实现各页面的差异化。 - 由
Admin实例持有数据库引擎。 你不需要向每个视图传入会话。
列表页选项
| Django Admin | starlette-admin | 说明 |
|---|---|---|
list_display |
fields 减去 exclude_fields_from_list |
一份字段列表驱动所有页面。 |
使用可调用对象或 @admin.display 的 list_display |
ComputedField,或任意字段上的 getter= |
例如,ComputedField("full_name", getter=lambda request, obj: ...)。在带类型的字段(如日期或图片字段)上使用 getter=,可保留该类型原有的渲染效果。 |
| 重新格式化真实列用于显示 | 字段上的 formatter= |
一个 dict[RequestAction, callable],因此列表、详情和导出可以有不同的格式化结果。在 Django 中需要可调用对象加上 admin_order_field 才能保持排序;而在这里该列始终可排序。 |
search_fields |
searchable_fields |
同时驱动全文搜索和过滤器构建器。 |
list_filter |
searchable_fields 结合每个字段的 filters= |
用户得到的是一个支持嵌套 AND/OR 分组的可视化构建器,而非固定的侧边栏。参见过滤器。 |
ordering |
fields_default_sort |
例如,[("created_at", True)] 表示按降序排序。 |
admin_order_field / 可排序性 |
sortable_fields |
默认情况下所有字段均可排序。 |
list_editable |
inline_editable_fields |
用户选中单元格后即可就地编辑。 |
list_per_page |
page_size、page_size_options |
控制分页上限。 |
date_hierarchy |
日期过滤器,如 between 和 in the past |
没有专门的层级下钻工具栏;过滤器构建器可以覆盖这一场景。 |
empty_value_display |
一个 formatter= 条目,或 null_template |
格式化器会收到 None 值,因此可以用占位内容替代。null_template 则替换渲染出来的标记。 |
表单
| Django Admin | starlette-admin | 说明 |
|---|---|---|
fields / exclude |
fields、exclude_fields_from_create、exclude_fields_from_edit |
控制表单字段的可见性。 |
fieldsets |
form_layout |
用 FieldsetWidget、TabsWidget、GridWidget 和 RowWidget 自由组合。 |
readonly_fields |
字段上的 read_only=True |
你也可以将该字段从创建和编辑视图中排除。 |
prepopulated_fields |
SlugField("slug", populate_from="title") |
同样的实时 slug 生成行为。 |
autocomplete_fields、raw_id_fields |
HasOne / HasMany 的默认行为 |
关联部件是开箱即用、支持服务端搜索的 Select2 输入框。 |
filter_horizontal / filter_vertical |
HasMany |
渲染为可搜索的多选组件。 |
formfield_overrides |
fields 列表中的显式条目 |
直接替换自动检测的字段:fields = ["id", TextAreaField("bio")] |
| 自定义表单校验 | 字段的 validators=,或钩子中的 FormValidationError |
参见校验器。 |
表单字段的 to_python() / 自定义类型转换 |
字段上的 parser= |
按 RequestAction 替换字段的默认表单解析或导入解析逻辑。 |
| 模型表单的帮助文本 | help_text= |
在任何字段定义上都可用。 |
字段集示例
form_layout 比字段集更进一步:你还可以构建选项卡、响应式网格和嵌套布局。参见表单布局。
内联
在外键无歧义时,starlette-admin 会自动检测外键,并且支持复合外键。高级配置参见内联表单。
动作
from starlette_admin import ActionSelection, action, flash
class ArticleView(ModelView):
actions = ["make_published", "delete"]
@action(
name="make_published",
text="Mark selected articles as published",
confirmation="Publish the selected articles?",
)
async def make_published(
self, request: Request, selection: ActionSelection
) -> None:
for article in await selection.rows():
article.published = True
flash(request, "Articles published")
Django Admin 传入的是 QuerySet,而 starlette-admin 的处理函数接收的是一个 ActionSelection 对象。该对象会惰性解析行、主键和当前生效的过滤器,并且在用户勾选所有匹配记录时行为完全相同。
动作还可以在确认对话框中渲染自定义 HTML 表单,这在 Django Admin 中意味着需要构建一个中间页面。对于行级操作,请使用 @row_action 和 @link_row_action,它们在 Django Admin 中没有对应概念。
权限与认证
Django Admin 将工作委托给 django.contrib.auth。starlette-admin 把问题拆分为两部分:AuthProvider 回答“这个用户是谁”,而按视图方法回答“他能做什么”。
| Django Admin | starlette-admin |
|---|---|
django.contrib.auth 登录 |
AuthProvider(内置登录页)或 OAuthProvider(OIDC 重定向流程) |
request.user |
request.state.admin_user |
has_module_permission |
视图上的 is_accessible(request) |
has_view_permission |
can_view_detail(request) |
has_add_permission |
can_create(request) |
has_change_permission |
can_edit(request) |
has_delete_permission |
can_delete(request) |
按用户的 get_readonly_fields |
can_access_field(request, field) |
| 无对应概念 | can_export(request)、can_import(request)、is_action_allowed(request, name) |
下面的视图将删除操作限制为具有 admin 角色的用户:
class ArticleView(ModelView):
def can_delete(self, request: Request) -> bool:
return "admin" in request.state.admin_user.roles
每个 can_* 方法都会接收请求,因此授权决策可以读取当前用户、HTTP 请求头或请求上的任何其他信息。
保存钩子与信号
| Django Admin | starlette-admin | 说明 |
|---|---|---|
save_model(request, obj, form, change) |
视图上的 before_create / before_edit |
原生异步,并同时接收解析后的表单数据和模型实例。 |
delete_model |
before_delete |
处理删除前的逻辑。 |
post_save 及其他信号 |
事件 | 例如,admin.events.on(AdminEvent.AFTER_CREATE, handler) 会向所有视图广播。 |
LogEntry 变更历史 |
用事件系统自行构建 | 订阅 AFTER_CREATE、AFTER_EDIT 和 AFTER_DELETE 来填充你自己的审计表。 |
messages.success(request, ...) |
flash(request, ...) |
参见Flash 消息。 |
站点级配置
| Django Admin | starlette-admin |
|---|---|
admin.site.site_header、site_title |
Admin(title="...") |
| 通过模板覆盖自定义 logo | Admin(logo_url="...", login_logo_url="...", favicon_url="...") |
AdminSite.index_template |
Admin(index_view=...),配合部件打造丰富的仪表盘 |
templates/admin/ 中的模板覆盖 |
Admin(templates_dir="..."),参见模板 |
多个 AdminSite 实例 |
挂载在不同应用路径上的多个 Admin 实例 |
ModelAdmin.get_queryset |
SQLAlchemy 后端的 get_list_query、get_count_query 或 get_detail_query |
USE_I18N、LANGUAGES |
Admin(i18n_config=I18nConfig(default_locale="fr")) |
TIME_ZONE |
Admin(timezone_config=TimezoneConfig(...)),参见i18n 与时区 |
切换后你能获得什么
- 端到端异步: 处理函数、生命周期钩子和部件回调都可以是协程,在与 FastAPI 端点相同的事件循环上运行。
- 数据库灵活性: 无论你使用 SQLAlchemy、SQLModel、通过 MongoEngine 或 Beanie 访问的 MongoDB,还是 Tortoise ORM,同一套 admin 配置均适用。
- 内置导出与导入: 支持 CSV、JSON 和 PDF,并通过
tablib支持 Excel 等其他格式。可以直接导出记录,也可以通过预览优先的向导导入批量数据;向导强制执行行级校验,并支持可选的主键 upsert。参见导出与导入。 - 仪表盘部件: 统计卡片、ApexCharts 和布局网格可组合成索引页和自定义视图,无需外部主题软件包即可构建仪表盘。参见自定义视图与部件。
- 现代化用户界面: Tabler(Bootstrap 5)默认提供深色模式、列可见性切换和搜索高亮。
需要你自己提供的部分
- 认证: 没有捆绑的用户模型或权限数据库。请针对你的应用已有的数据存储实现
AuthProvider.authenticate()。 - 审计日志: starlette-admin 不会生成
LogEntry表。请将事件系统接入你自己的审计表。 - 模型级 UI 配置: Django 的一些便利特性,例如模型级的
choices、verbose_name和校验器,无法直接迁移。请在 starlette-admin 的字段上声明这些配置,使用EnumField、label=和validators=。