FastAPI系列20:fastapi-amis-admin,即开即用的后台框架(2)

发布于:2025-06-12 ⋅ 阅读:(33) ⋅ 点赞:(0)


在上一节FastAPI系列19:fastapi admin,即开即用的后台框架(1),我们讲解了fastapi-amis-admin的基本使用,本节我们深入学习fastapi-amis-admin。在fastapi-amis-admin中 AdminSite代表着整个后台应用,它可以包含多个AdminApp,而每一个AdminApp中可以有多个AdminGroup作为页面导航分组,每个AdminGroup可以包含多个PageSchemaAdmin管理页面,这样就构成了整个后台应用基本结构。

核心概念

1、AdminSite, 后台系统的核心管理类

AdminSite继承自BaseAdminSite,负责整个后台的初始化、路由挂载、配置管理和资源注册。

初始化后台站点配置
接受 Settings、FastAPI 实例和可选数据库 engine 参数。
Settings 用来配置后台是否启动调试、挂载路径、数据库连接地址、CDN 路径、AMIS 版本等 。
在初始化时会配置 FastAPI 应用对象,包括路由路径、文档地址、依赖注入等。

管理数据库引擎
内部维护默认 SQLAlchemy 同步/异步数据库引擎(由 Settings.database_url_async 或 engine 参数提供)。
后续注册的 ModelAdmin 和 AdminApp 默认使用该数据库连接 。

注册与挂载后台功能
支持通过 @site.register_admin 装饰器注册 ModelAdmin, PageAdmin, FormAdmin 等多种后台资源。
mount_app(app) 方法将后台整套界面挂载至主 FastAPI,默认路径为 /admin/,同时支持 OpenAPI 和 Redoc 文档的副本接口 。

支持自定义子类扩展
用户可继承 AdminSite 重写模板(template_name)、菜单结构、自定义静态资源、权限校验逻辑等 。
示例:覆盖 get_page() 方法修改站点名称和 logo,或卸载默认 DocsAdmin/ReDocsAdmin 。

权限与认证集成
内置权限判断 has_page_permission,可通过集成 fastapi-user-auth 等组件实现用户登录、RBAC 权限控制 。
支持全局依赖注入和路由权限验证的穿透机制。

2、AdminApp,用于模块化组织后台功能

AdminApp 是 FastAPI‑Amis‑Admin 中的一个重要管理单元,位于 AdminSite 与具体管理类(如 ModelAdmin、PageAdmin)之间,用于模块化组织后台功能。

隶属关系
AdminSite 是顶层后台应用,它可以注册多个 AdminApp。
每个 AdminApp 又可以注册多个后台管理类(如模型、页面、表单等) 。

功能组织
支持将相关功能模块化管理,如:BlogApp 集中管理博客相关 CRUD;UserApp 管理用户功能。
可以注册 ModelAdmin、PageAdmin、FormAdmin 等多个管理资源。

自定义配置
支持独立 router_prefix(URL 前缀)与 AMIS 风格页面配置。
可选配置独立数据库连接(通过 engine 参数进行异步或同步 DB 操作) 。

层级嵌套
AdminApp 本身也是可注册的管理类,因此可以作为“子后台”,嵌套在另一个 AdminApp 或 AdminSite 中使用:比如 AdminSite → AdminAPP1 → AdminAPP11、AdminAPP12 等

3、AdminGroup,用于组织页面导航分组

AdminGroup是 fastapi-amis-admin 中用来组织页面导航分组的组件,专门用来聚合多个页面项(如 PageAdmin、LinkAdmin、IframeAdmin 等),统一展示在后台侧边栏菜单中的一个折叠分组里。

页面分组导航
允许多个子页面以逻辑分类方式展示,如“文档管理”分组下可以放 Docs、ReDocs、API 文档等页面。
提高后台界面的可读性和可维护性。

权限自动过滤
调用 get_page_schema_children(request) 获取子页面,在渲染前会根据当前用户权限自动过滤(无权限则不显示)。
子页面嵌套在组中,但权限仍独立控制。

可组合与可迭代
实现迭代接口,可在 AdminApp 或 AdminSite 注册时统一遍历生成路由等处理。
支持动态注册子页面。

4、PageSchemaAdmin及其子类PageAdmin、LinkAdmin、IframeAdmin、TemplateAdmin

PageSchemaAdmin 是 fastapi‑amis‑admin 中用于管理后台导航页面的核心基类,提供页面显示和权限控制的基本能力,它包含 PageAdmin、LinkAdmin、IframeAdmin、TemplateAdmin 等具体页面管理子类。它是页面导航项的标准接口和权限网关,定义如何展示在后台导航中、何时可访问,并生成 AMIS 所需的页面 Schema。

具体页面管理子类
静态页面:通过设置 PageAdmin.page 提供 AMIS JSON 或通过 get_page() 方法动态获取页面内容;
外链页面:使用 LinkAdmin 定义跳转链接;
嵌入页面:使用 IframeAdmin 嵌入第三方连接;
模板页面:使用 TemplateAdmin 渲染 Jinja2 模板。

5、BaseActionAdmin及其子类ModelAdmin、FormAdmin

BaseActionAdmin 是 fastapi-amis-admin 框架中用于实现页面操作行为(如按钮、表单提交)的基类,基于 AMIS 中的 Action 概念,BaseActionAdmin 允许你在页面上定义附加行为(例如按钮触发的弹窗、确认对话框、执行操作等)。
ModelAdmin、FormAdmin 等继承自 BaseActionAdmin,因此具备“行为”注册能力,如创建、更新、删除、批量操作按钮。

6、PageSchemaAdmin 及BaseActionAdmin的结构关系

BaseAdmin
+AdminApp app
+AdminSite site
+str unique_id
+register_routes()
PageSchemaAdmin
<> BaseAdmin
+PageSchema page_schema
LinkAdmin
<> PageSchemaAdmin
+str link
IframeAdmin
<> PageSchemaAdmin
+str src
PageAdmin
<> RouterAdmin
<> PageSchemaAdmin
+AmisPage page
RouterAdmin
<> RouterMixin
<> BaseAdmin
TemplateAdmin
<> PageAdmin
+Jinja2Templates templates
BaseActionAdmin
<> PageAdmin
+Action action
FormAdmin
<> BaseActionAdmin
+Form form
ModelAdmin
<> BaseActionAdmin
<> SQLModelCrud
+Field/Column definitions

基础教程

1、页面管理

普通页面
我们在前一节的“Hello World”示例的基础上,再实现一个获取当前时间的页面。
在main.py中的site.mount_app(app)上方添加:

import time
from fastapi import Request

@site.register_admin
class CurrentTimePageAdmin(admin.PageAdmin):
    page_schema = 'Current Time Page'

    page = Page.model_validate(
        {
            "type": "page",
            "title": "Current Time Page",
            "body": {
				"type": "markdown",
				"value": "**当前时间:** " + time.strftime('%Y-%m-%d %H:%M:%S')
			}
        }
    )

链接页面
LinkAdmin实现在菜单列表显示一个链接跳转菜单,点击菜单后将通过打开一个新的浏览器标签,访问设置的链接:

from fastapi_amis_admin.admin import admin
from fastapi_amis_admin.amis import PageSchema


@site.register_admin
class GitHubLinkAdmin(admin.LinkAdmin):
    # 通过page_schema类属性设置页面菜单信息;
    page_schema = PageSchema(label='AmisLinkAdmin', icon='fa fa-github')
    # 设置跳转链接
    link = 'https://example.com'

iframe页面
IframeAdmin实现在菜单列表显示一个菜单,点击菜单后将通过在当前页面内嵌一个框架。使用方法与LinkAdmin 非常相似,不同的仅仅是链接的打开方式,

@site.register_admin
class ReDocsAdmin(admin.IframeAdmin):
    # 设置页面菜单信息
    page_schema = PageSchema(label='Redocs', icon='fa fa-book')

    # 设置跳转链接
    @property
    def src(self):
        return self.app.site.settings.site_url + '/redoc'

2、表单管理

FormAdmin实现在菜单列表显示一个菜单,点击菜单后将展现一个amis表单页面。

from fastapi_amis_admin.admin import admin
from fastapi_amis_admin.crud import BaseApiOut
from fastapi_amis_admin.models.fields import Field
from pydantic import BaseModel
from starlette.requests import Request
from fastapi_amis_admin.amis import Form
from typing import Any

@site.register_admin
class UserLoginFormAdmin(admin.FormAdmin):
    page_schema = 'UserLoginForm'
    # 配置表单信息, 可省略
    form = Form(title='这是一个测试登录表单', submitText='登录')

    # 创建表单数据模型
    class schema(BaseModel):
        username: str = Field(..., title='用户名', min_length=3, max_length=30)
        password: str = Field(..., title='密码')

    # 处理表单提交数据
    async def handle(self, request: Request, data: BaseModel, **kwargs) -> BaseApiOut[Any]:
        if data.username == 'amisadmin' and data.password == 'amisadmin':
            return BaseApiOut(msg='登录成功!', data={'token': 'xxxxxx'})
        return BaseApiOut(status=-1, msg='用户名或密码错误!')

3、模板管理

在某些情况下,amis页面可能并不方便实现你的复杂界面展示,或者你更加倾向于使用模板渲染方式展示管理页面,这时你可以使用TemplateAdmin 实现你的需求。
在根目录下创建模板目录templates,并在模板目录创建simple.html文件,内容如下:

from fastapi_amis_admin.admin.admin import Jinja2Templates
import datetime
from typing import Dict

@site.register_admin
class SimpleTemplateAdmin(admin.TemplateAdmin):
    page_schema = PageSchema(label='SimpleTemplate', icon='fa fa-link')
    templates: Jinja2Templates = Jinja2Templates(directory='templates')
    template_name = 'simple.html'

    async def get_page(self, request: Request) -> Dict[str, Any]:
        return {'current_time': datetime.datetime.now()}

以下是模版文件代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Current Time</title>
</head>
<body>
    <h1>Current Time</h1>
    <p>The current time is: {{ current_time }}</p>
</body>
</html>

4、模型管理

模型管理在后台管理中是最为常用的一个管理类,fastapi-amis-admin目前已经实现针对数据模型常用的各种基本操作,并且你仍然可以在此基础上做出更多个性化的拓展。
SQLAlchemy Schema

from sqlalchemy import String, Integer, Boolean, ForeignKey, Select 
from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column 
from typing import Optional


class Base(DeclarativeBase):
    pass


class CategorySchema(BaseModel):
    id: Optional[int] = Field(default=None, primary_key=True, nullable=False)
    name: str = Field(title="CategoryName")
    description: str = Field(default="", title="CategoryDescription")

    class Config:
        # orm_mode = True
        from_attributes = True

# 创建SQLAlchemy 2.0模型,详细请参考: https://docs.sqlalchemy.org/en/20/orm/quickstart.html
class Category(Base):
    __tablename__ = "category"
    __pydantic_model__ = CategorySchema  # 指定模型对应的Schema类.省略可自动生成,但是建议指定.

    id: Mapped[int] = mapped_column(primary_key=True, nullable=False)
    name: Mapped[str] = mapped_column(String(100), unique=True, index=True, nullable=False)
    description: Mapped[str] = mapped_column(String(255), default="")

Admin Page

# 注册ModelAdmin
@site.register_admin
class CategoryAdmin(admin.ModelAdmin):
    page_schema = '分类管理'
    # 配置管理模型
    model = Category