django-baton

GitHub
985 96 简单 1 次阅读 1周前MIT语言模型图像插件
AI 解读 由 AI 自动生成,仅供参考

django-baton 是一款专为 Django 框架打造的现代化后台管理界面增强工具。它基于 Bootstrap 5 和 Google Material Symbols 构建,旨在将 Django 原生略显单调的管理后台升级为美观、响应式且功能强大的操作面板,完美适配各类终端设备。

该工具主要解决了开发者在定制后台界面时耗时费力、原生功能有限以及缺乏智能化辅助的痛点。通过集成前沿的 AI 能力,django-baton 让后台管理变得更加智能高效:它支持自动文本翻译、内容摘要生成、写作纠错,甚至能利用 DALL·E 3 直接生成图片或借助计算机视觉自动为图像添加描述标签。此外,它还提供了丰富的主题定制方案和灵活的菜单配置,大幅降低了 UI 个性化的门槛。

django-baton 非常适合正在使用 Django 进行开发的工程师、全栈开发者以及需要快速交付高质量后台系统的技术团队。对于希望在不重写核心逻辑的前提下,显著提升管理后台用户体验并融入 AI 工作流的项目而言,这是一个极具价值的选择。其独特的 AI 深度集成特性,让传统的 CMS 管理界面具备了现代智能应用的雏形,帮助开发者更专注于业务逻辑而非界面打磨。

使用场景

某电商初创团队正在快速搭建后台管理系统,需要频繁处理多语言商品上架、撰写营销文案以及为海量商品图添加描述。

没有 django-baton 时

  • 多语言维护繁琐:运营人员需手动将中文商品详情翻译成英文和西班牙文,不仅耗时且容易出现术语不一致,导致多语言站点内容不同步。
  • 图片无障碍缺失:面对数千张新上传的商品图,开发人员不得不编写脚本或人工逐一填写 alt 属性,否则无法满足 SEO 和无障碍访问标准。
  • 文案创作效率低:市场部在后台编辑促销介绍时,缺乏辅助工具,只能切换到外部 AI 网站生成文案再复制回来,工作流频繁中断。
  • 界面体验陈旧:默认的 Django Admin 界面在手机端操作困难,响应式布局缺失,导致仓库管理员无法在移动设备上高效核对库存。

使用 django-baton 后

  • 一键自动翻译:集成 django-modeltranslation 后,运营人员在保存中文内容时,django-baton 利用 AI 自动填充其他语言字段,确保全球站点内容实时一致。
  • 智能图像描述:借助计算机视觉功能,系统能自动分析上传的商品图并生成准确的 alt 文本,彻底解放了人工标注的成本。
  • 内置写作助手:编辑页面直接嵌入 AI 功能,支持文本摘要、润色纠错甚至通过 DALL·E 3 生成配图,让文案创作在后台内闭环完成。
  • 现代化移动体验:基于 Bootstrap 5 重构的界面完美适配手机和平板,仓库人员可随时随地通过响应式菜单流畅管理订单。

django-baton 将原本割裂的 AI 工作流无缝融入 Django 后台,把繁琐的内容运维变成了智能化的自动化流程。

运行环境要求

操作系统
  • 未说明 (适用于任何支持 Django 的操作系统)
GPU
  • 不需要本地 GPU
  • AI 功能(如图像生成、视觉分析)通过 API 调用外部服务(如 DALL·E 3, GPT-4),需配置 Baton 订阅密钥
内存

未说明 (取决于底层 Django 项目需求)

依赖
notes该工具是 Django 管理界面的增强插件,而非独立的 AI 模型运行环境。使用 AI 功能(翻译、摘要、纠错、图像生成/分析)必须配置 'BATON_CLIENT_ID' 和 'BATON_CLIENT_SECRET' 以连接外部 AI 服务,无需在本地部署大型语言模型或计算机视觉模型。
python未明确指定 (需匹配所安装的 Django 版本:Django >= 5.x 对应 Baton >= 5.0;Django 2.1-5.x 对应 Baton 4.x)
Django (>= 2.1)
Bootstrap 5 (前端)
Google Material Symbols (前端)
jQuery (前端)
django-modeltranslation (可选,用于自动翻译)
django-baton hero image

快速开始

Django Baton

PyPI version Build status Documentation Status License Downloads

一款酷炫、现代、响应式且融合了AI技术的Django管理后台界面,基于Bootstrap 5和Material Symbols构建。

📖 文档     |     🚀 在线演示     |     报告Bug     |     请求功能


Django Baton将标准的Django管理后台转变为一个功能强大、直观且视觉上极具吸引力的界面。它基于Bootstrap 5和Google Material Symbols构建,具备完全的响应式设计,并将前沿的AI功能直接集成到你的管理面板中。

立即体验在线演示!

使用用户demo和密码demo登录,亲身体验Django Baton的各项功能。 https://django-baton.sqrt64.it/


📣 最新动态?

  • Baton 5.x: 进行了全面的视觉重新设计,并从FontAwesome迁移到Google Material Symbols,以提供更简洁现代的图标集,详情请参阅迁移指南
  • Baton 4.2.1:BatonAiImageField中集成了计算机视觉能力,进行了多项细微的样式改进,并合并了社区提交的多个Pull Request。
  • Baton 4.2.0: 引入了用于自动生成图片alt属性的计算机视觉功能。
  • Baton 4.0.*:推出了一系列强大的AI功能!
    • 自动翻译(与django-modeltranslation集成)。
    • 文本摘要功能,助力内容创作。
    • 文本校正功能,提升写作质量。
    • 使用DALL·E 3生成图像。
    • 此版本还引入了强大的主题支持,使自定义变得更加容易。大多数主题更改不再需要重新编译JavaScript应用。

🎨 探索主题! 发现即用型主题,并从django-baton-themes仓库中获取灵感: github.com/otto-torino/django-baton-themes


Django Baton AI功能展示 Baton的AI功能示例。

📋 目录

核心特性

兼容性说明:

  • 对于 Django >= 5.x: 使用Baton >= 5.0
  • 对于 5.x > Django >= 2.1: 使用Baton == 4.x
  • 对于 较旧的Django版本 (1.x): 使用 django-baton==1.13.2

Baton的设计核心原则是:尽量减少对Django模板的覆盖。样式主要通过CSS实现,而JavaScript则用于实现动态功能。

  • 现代技术栈: 基于Bootstrap 5和Google Material Symbols构建。
  • 完全响应式: 无缝适配各种屏幕尺寸。
  • 🧠 AI赋能:
    • 自动翻译(与django-modeltranslation集成)。
    • 文本摘要与校正。
    • 图像视觉(为alt文本生成描述)。
    • 图像生成(例如DALL·E 3)。
    • (AI功能需要Baton订阅密钥)
  • 可定制菜单: 灵活的字典配置侧边栏导航。
  • 🎨 主题支持: 轻松自定义外观和风格。
  • 增强型搜索: 可配置的全局搜索字段,支持自动补全。
  • 高级列表过滤器: 包括文本输入、下拉菜单和多选过滤选项。
  • 改进的表单:
    • 开箱即用的字段集和内联表单标签页界面。
    • 固定提交行,提升长表单的可用性。
    • 可折叠的堆叠内联条目。
    • 延迟加载上传图片及图片预览。
  • 灵活的包含机制: 可轻松将自定义模板注入到变更列表和变更表单页面中。
  • 动态行属性: 可为变更列表的行或单元格添加自定义HTML属性(类名、data属性、标题等)。
  • 用户体验优化:
    • 可选的模态窗口显示变更列表过滤器。
    • 可选的“表单模式”用于变更列表过滤器(一次应用多个过滤器)。
    • 未保存更改的确认提示。
    • 多部分表单上传时的加载指示器。
    • 用于管理消息的Toast通知。
    • Gravatar支持。
  • 开发者友好: 可通过CSS变量进行自定义,或通过重新编译提供的JavaScript应用来实现更深层次的修改。
  • 多语言支持: 包含意大利语(IT)和波斯语(FA)翻译。

前端技术: Baton利用Bootstrap 5实现样式和响应式布局,使用Google Material Symbols作为图标库,并借助jQuery进行DOM操作。所有资源被编译成一个单独的JavaScript文件,以实现优化的交付。

🛠️ 安装

  1. 通过 pip 安装:

    pip install django-baton
    

    或者,要使用最新的开发版本,请将仓库克隆到您的项目中:

    git clone [https://github.com/otto-torino/django-baton.git](https://github.com/otto-torino/django-baton.git)
    
  2. 添加到 INSTALLED_APPS 在您项目的 settings.py 中,将 baton 放在 django.contrib.admin 之前,并将 baton.autodiscover 放在列表的最末尾

    # settings.py
    INSTALLED_APPS = [
        # ... 其他应用 ...
        'baton',  # 必须放在 django.contrib.admin 之前
        'django.contrib.admin',
        # ... 其他应用 ...
        'baton.autodiscover', # 必须是最后一个应用
    ]
    
  3. 运行迁移:

    python manage.py migrate
    
  4. 更新 URL 配置: 在您项目的主 urls.py 文件中,将 django.contrib.admin 替换为 baton.autodiscover.admin,并包含 Baton 的 URL 配置:

    # urls.py
    # from django.contrib import admin # 移除或注释掉这一行
    from baton.autodiscover import admin # 导入 Baton 的管理后台
    from django.urls import path, include
    
    urlpatterns = [
        path('admin/', admin.site.urls),
        path('baton/', include('baton.urls')),
        # ... 您其他的 URL 模式 ...
    ]
    

为什么要在 INSTALLED_APPS 中有两个条目?

  • baton:需要放在 django.contrib.admin 之前,因为它会覆盖 Django 默认的一些管理模板,并重置 CSS 样式。
  • baton.autodiscover:这个模块必须是 INSTALLED_APPS 中的最后一个应用。Baton 使用自定义的 AdminSite 类,允许以 Django 风格的方式自定义诸如 site_headerindex_title 等变量(而不是直接覆盖模板)。通常情况下,自定义的 AdminSite 需要手动注册所有应用。而 baton.autodiscover 模块巧妙地自动化了这一过程,它会自动注册所有已经通过 Django 默认 AdminSite 注册的应用,从而确保您的所有模型都能出现在 Baton 管理后台中。为了使这一功能正常工作,其他所有应用都必须在此之前已经被处理过。

⚙️ 配置

在您的 settings.py 中定义 BATON 字典,以自定义管理后台的各个方面。


# settings.py
from baton.ai import AIModels # 如果使用 AI 功能

BATON = {
    'SITE_HEADER': 'Baton 管理后台',
    'SITE_TITLE': 'Baton 管理',
    'INDEX_TITLE': '站点管理仪表板',
    'SUPPORT_HREF': 'https://github.com/otto-torino/django-baton/issues',
    'COPYRIGHT': '版权 © 2025 <a href="https://www.otto.to.it">Otto srl</a>', # HTML 是安全的
    'POWERED_BY': '<a href="https://www.otto.to.it">Otto srl</a>', # HTML 是安全的
    'CONFIRM_UNSAVED_CHANGES': True,
    'SHOW_MULTIPART_UPLOADING': True,
    'ENABLE_IMAGES_PREVIEW': True,
    'CHANGELIST_FILTERS_IN_MODAL': False,
    'CHANGELIST_FILTERS_ALWAYS_OPEN': False,
    'CHANGELIST_FILTERS_FORM': False,
    'CHANGEFORM_FIXED_SUBMIT_ROW': True,
    'COLLAPSABLE_USER_AREA': True,
    'MENU_ALWAYS_COLLAPSED': False,
    'MENU_TITLE': '主菜单',
    'MESSAGES_TOASTS': False, # 对所有消息启用,或例如 ['warning', 'error']
    'GRAVATAR_DEFAULT_IMG': 'retro',
    'GRAVATAR_ENABLED': True,
    'LOGIN_SPLASH': '/static/core/img/login-splash.png', # 登录界面背景图路径
    'FORCE_THEME': None, # 'light' 或 'dark',或设置为 None 允许用户切换
    'BATON_CLIENT_ID': 'your_client_id_for_ai_features',
    'BATON_CLIENT_SECRET': 'your_client_secret_for_ai_features',
    'IMAGE_PREVIEW_WIDTH': 200,
    'AI': {
        # "MODELS": "myapp.utils.get_ai_models_config", # 函数路径
        "IMAGES_MODEL": AIModels.BATON_DALL_E_3,
        "VISION_MODEL": AIModels.BATON_GPT_4O_MINI,
        "SUMMARIZATIONS_MODEL": AIModels.BATON_GPT_4O_MINI,
        "TRANSLATIONS_MODEL": AIModels.BATON_GPT_4O,
        'ENABLE_TRANSLATIONS': True,
        'ENABLE_CORRECTIONS': True,
        'CORRECTION_SELECTORS': [
            "textarea",
            "input[type=text]:not(.vDateField):not([name=username]):not([name*=subject_location])"
        ],
        "CORRECTIONS_MODEL": AIModels.BATON_GPT_3_5_TURBO,
    },
    'MENU': (
        { 'type': 'title', 'label': '主导航', 'apps': ('auth', ), 'icon': 'apps'},
        {
            'type': 'app',
            'name': 'auth',
            'label': '认证',
            'icon': 'lock',
            'models': (
                { 'name': 'user', 'label': '用户', 'icon': 'group' },
                { 'name': 'group', 'label': '组', 'icon': 'verified_user' },
            )
        },
        { 'type': 'title', 'label': '内容管理', 'apps': ('flatpages', ), 'icon': 'web_stories' },
        { 'type': 'model', 'label': '静态页面', 'name': 'flatpage', 'app': 'flatpages', 'icon': 'article' },
        { 'type': 'free', 'label': '自定义链接', 'url': 'https://www.google.com', 'icon': 'link', 'perms': ('flatpages.add_flatpage', 'auth.change_user') },
        {
            'type': 'free',
            'label': '嵌套菜单',
            'icon': 'menu_open',
            'default_open': True,
            'children': [
                { 'type': 'model', 'label': 'A 模型', 'name': 'mymodelname', 'app': 'myapp', 'icon': 'settings' },
                { 'type': 'free', 'label': '另一个链接', 'url': 'https://www.example.com', 'icon': 'public' },
            ]
        },
    )
}

详细配置选项:

  • SITE_HEADERCOPYRIGHTPOWERED_BY:支持 HTML 内容。
  • SUPPORT_HREF:支持链接的 URL。
  • CONFIRM_UNSAVED_CHANGES(默认:True):离开未保存表单时提示。(注意:依赖 jQuery serialize(),可能无法检测所有更改。)
  • SHOW_MULTIPART_UPLOADING(默认:True):多部分表单提交时显示加载动画。
  • ENABLE_IMAGES_PREVIEW(默认:True):显示图片预览。可通过 .baton-image-preview CSS 自定义样式。
  • CHANGELIST_FILTERS_IN_MODAL(默认:False):若为 True,筛选器将显示在模态框中。
  • CHANGELIST_FILTERS_ALWAYS_OPEN(默认:False):若为 True(且模态筛选器为 False),筛选器将始终处于打开状态。
  • CHANGELIST_FILTERS_FORM(默认:False):若为 True,筛选器将被视为一个表单。
  • CHANGEFORM_FIXED_SUBMIT_ROW(默认:True):将提交行固定在底部。
  • COLLAPSABLE_USER_AREA:若为 True,侧边栏中的用户区域初始状态为折叠。(请参阅文档以了解默认行为)。
  • MENU_ALWAYS_COLLAPSED(默认:False):若为 True,菜单默认会折叠。
  • MENU_TITLE(默认:'Menu'):侧边栏菜单标题。
  • MESSAGES_TOASTS(默认:False):用于管理员消息的通知提示(对所有消息启用,或如 ['warning', 'error'] 列表)。
  • GRAVATAR_DEFAULT_IMG(默认:'retro'):Gravatar 的默认头像。
  • GRAVATAR_ENABLED(默认:True):显示用户的 Gravatar 头像。
  • LOGIN_SPLASH:登录页面背景图的路径。
  • FORCE_THEME(默认:None):可强制设置主题为 'light''dark'
  • BATON_CLIENT_IDBATON_CLIENT_SECRET:来自 baton.sqrt64.it 的 AI 功能订阅密钥。
  • IMAGE_PREVIEW_WIDTH(默认:200):BatonAiImageField 预览的宽度(像素)。

AI 配置

Django Baton 集成了 AI 功能,以辅助内容创建和管理。

可用模型(在 baton.ai.AIModels 中):

  • BATON_GPT_3_5_TURBOBATON_GPT_4_TURBOBATON_GPT_4O:用于翻译、摘要生成和文本校正。
  • BATON_GPT_4O_MINI:默认用于非图像相关的文本任务及图像视觉处理。
  • BATON_DALL_E_3:默认用于图像生成。

配置:BATON['AI'] 中设置首选模型:

"AI": {
    "IMAGES_MODEL": AIModels.BATON_DALL_E_3,
    "VISION_MODEL": AIModels.BATON_GPT_4O_MINI,
    # ... 等等
}

或者通过 "MODELS": "myapp.utils.get_ai_models_config" 使用函数路径。

翻译功能: 需要 django-modeltranslation 扩展。启用并设置模型:

'BATON_CLIENT_ID': 'your_client_id',
'BATON_CLIENT_SECRET': 'your_client_secret',
'AI': {
    'ENABLE_TRANSLATIONS': True,
    'TRANSLATIONS_MODEL': AIModels.BATON_GPT_4O,
    # ...
},

注意: 请仔细检查 AI 生成的翻译结果。长文本翻译可能需要增加服务器超时时间。

文本校正:

'AI': {
    'ENABLE_CORRECTIONS': True,
    'CORRECTIONS_MODEL': AIModels.BATON_GPT_4O,
    'CORRECTION_SELECTORS': [
        "textarea",
        "input[type=text]:not(.vDateField):not([name=username]):not([name*=subject_location])"
    ],
    # ...
},

与选择器匹配的字段旁边会出现一个图标,点击即可触发校正。同时按住 Ctrl 键并左键单击也会触发校正。 AI 校正截图

摘要生成、图像视觉与图像生成: 详见 Baton AI 深度解析 章节。

菜单配置

通过 BATON['MENU'] 自定义侧边栏。

项类型:

  • title: 部分标题。
    • labelapps(可选)、perms(可选)、children(可选)、default_open(可选)、icon(可选 Material Symbol)。
  • app: 链接到一个 Django 应用。
    • name(小写应用标签)、label(可选)、icon(可选)、models(可选元组,用于自定义模型列表)、default_open(可选)。
  • model: 链接到某个模型的更改列表。
    • name(小写模型名)、app(小写应用标签)、label(可选)、icon(可选)。
  • free: 自定义链接。
    • labelurlicon(可选)、perms(可选)、re(可选用于高亮显示的正则表达式)、children(可选)、default_open(可选)。

具有子项的项的子项将被忽略。

搜索字段配置

在侧边栏中添加一个自动完成的搜索字段。

搜索字段截图

'SEARCH_FIELD': {
    'label': '搜索内容...', # 占位符
    'url': '/api/admin_search/',   # 您的搜索 API 端点
}

您在 url 处的 API 接收一个 text GET 参数,并应返回 JSON:

{
    "length": 1,
    "data": [
        { "label": "搜索结果标签", "url": "/admin/path/to/item/", "icon": "search" }
    ]
}

搜索 API 的 Django 视图示例:

# views.py
from django.http import JsonResponse
from django.contrib.admin.views.decorators import staff_member_required
# from myapp.models import YourModel # 您的模型

@staff_member_required
def admin_search_api(request):
    text = request.GET.get('text', None)
    response_data = []
    # 在此处实现您的搜索逻辑
    # 示例:
    # if text:
    #     items = YourModel.objects.filter(title__icontains=text)[:10]
    #     for item in items:
    #         response_data.append({
    #             'label': str(item),
    #             'url': f'/admin/myapp/yourmodel/{item.id}/change/', # 调整 URL
    #             'icon': 'article', # Material Symbol 名称
    #         })
    return JsonResponse({'length': len(response_data), 'data': response_data})

🤖 Baton AI 深度解析

AI 功能需要 BATON_CLIENT_IDBATON_CLIENT_SECRET。有关模型选择,请参阅 AI 配置

Baton 使用 baton.sqrt64.it 的 API 来生成响应,但可以通过以下设置更改端点的基本路径:

BATON = {
    # ...
    "BATON_AI_API_BASE_PATH": "http://localhost:1323",
    # ...
}

在这种情况下,您应该为 AI 功能实现自己的端点。

自动翻译

如果 ENABLE_TRANSLATIONS 设置为 True 并且使用了 django-modeltranslation,则具有可翻译字段的表单上会显示“翻译”按钮。支持默认字段和 CKEditor。有关其他编辑器,请参阅 AI 钩子

错误修正

如果 ENABLE_CORRECTIONS 设置为 True,则文本字段附近(匹配 CORRECTION_SELECTORS)以及 CKEditor 字段中的图标会触发 AI 修正。差异会在模态窗口中显示。

文本摘要

在您的 ModelAdmin 中定义 baton_summarize_fields

# admin.py
class MyModelAdmin(admin.ModelAdmin):
    # ...
    baton_summarize_fields = {
        "source_field_name_it": [{ # 例如,'body_it'
            "target": "target_field_name_it", # 例如,'summary_it'
            "words": 140, # 大约
            "useBulletedList": True,
            "language": "it", # 可选,默认为 Django 当前语言
        },
        # ... 同一源字段的更多目标 ...
        ],
    }

源字段附近会出现按钮,用于为目标字段生成摘要。参数(wordsuseBulletedList)可以在 UI 中编辑。支持默认字段和 CKEditor。有关详细信息,请参阅 AI 钩子

图片生成

在您的模型中使用 BatonAiImageField

# models.py
from baton.fields import BatonAiImageField
from django.db import models
from django.utils.translation import gettext_lazy as _

class MyMediaModel(models.Model):
    ai_generated_image = BatonAiImageField(
        verbose_name=_("AI 生成的图片"),
        upload_to="ai_images/",
        subject_location_field='image_subject_location', # 可选:用于主体聚焦
        alt_field="image_alt_text" # 可选:用于 AI 生成的替代文本(参见图像视觉)
    )
    image_subject_location = models.CharField(max_length=7, default="50,50", blank=True)
    image_alt_text = models.CharField(max_length=255, blank=True)

字段附近的按钮会打开一个模态窗口,允许您根据文本提示生成图片。 或者,对于标准的 ImageField,可以使用 JavaScript 添加生成功能:

<script>
    Baton.AI.addImageGeneration('{{ widget.name }}'); // ImageField 的 widget.name
</script>

集成 django-subject-imagefield 的主体位置功能。通过 BATON 设置中的 IMAGE_PREVIEW_WIDTH 配置预览宽度。

图像视觉

为图片生成替代文本。

  1. 使用 BatonAiImageField: 在字段上设置 alt_fieldalt_chars(可选)、alt_language(可选)属性。主要适用于内联中的图片。

    # models.py
    image = BatonAiImageField(upload_to="news/", alt_field="image_alt_text", alt_chars=100)
    image_alt_text = models.CharField(max_length=150, blank=True)
    
  2. 使用 ModelAdmin 配置: 在您的 ModelAdmin 中定义 baton_vision_fields

    # admin.py
    class MyModelAdmin(admin.ModelAdmin):
        # ...
        baton_vision_fields = {
            "#id_form-0-image": [{ // CSS 选择器,用于指定图片字段(可 targeting 内联)
                "#id_image_field_name": [{ // 键必须是 CSS 选择器,指向图片输入或其预览
                    "target": "name_of_alt_text_field", // 同一模型/表单中的 CharField 名称
                    "chars": 80,                            // 可选:最大字符数(默认 100)
                    "language": "en",                       // 可选:描述的语言
                }],
            }
        }
    

    指定的图片字段附近会出现一个按钮。点击后,target 字段将被 AI 生成的描述填充。

统计小部件

在您的管理仪表板上显示一个显示 AI 功能使用情况统计的小部件。将以下内容添加到您的管理索引模板(通常是您覆盖的 admin/index.html):

{% load baton_tags %}

{% baton_ai_stats %}

Baton AI 统计小部件

AI 钩子

Django Baton 的 AI 功能会与表单字段交互,以获取和设置值。默认情况下,原生 HTML 输入框、文本区域以及由 django-ckeditor 管理的字段都受支持。若要为其他所见即所得(WYSIWYG)编辑器或自定义输入小部件添加支持,你需要定义 JavaScript 钩子。

将这些钩子定义放置在你的 admin/base_site.html 模板中,在 {% static 'baton/js_snippets/init_baton.js' %} 脚本标签 之前

<script src="{% static 'baton/app/dist/baton.min.js' %}"></script> {# 确保先加载 Baton 的主 JS #}
<script>
(function () {
    // 获取由自定义编辑器管理的所有字段 ID 列表的钩子。
    // 应返回字符串数组(字段 ID)。
    Baton.AI.getEditorFieldsHook = function () {
        // 例如针对假设的 'MyEditor':
        // if (window.MyEditor && typeof window.MyEditor.getAllInstanceIds === 'function') {
        //   return window.MyEditor.getAllInstanceIds();
        // }
        return []; // 针对你特定的编辑器实现
    };

    // 根据字段 ID 获取特定编辑器实例内容的钩子。
    // 应返回字符串内容,如果 fieldId 不是编辑器字段,则返回 null/undefined。
    Baton.AI.getEditorFieldValueHook = function (fieldId) {
        // 例如针对 'MyEditor':
        // if (window.MyEditor && typeof window.MyEditor.getInstance === 'function') {
        //   const editorInstance = window.MyEditor.getInstance(fieldId);
        //   return editorInstance ? editorInstance.getContent() : null;
        // }
        return null; // 针对你特定的编辑器实现
    };

    // 设置特定编辑器实例内容的钩子。
    // 如果 fieldId 对应于编辑器且成功设置了值,则返回 true;否则返回 false。
    Baton.AI.setEditorFieldValueHook = function (fieldId, value) {
        // 例如针对 'MyEditor':
        // if (window.MyEditor && typeof window.MyEditor.getInstance === 'function') {
        //   const editorInstance = window.MyEditor.getInstance(fieldId);
        //   if (editorInstance) {
        //     editorInstance.setContent(value);
        //     return true;
        //   }
        // }
        return false; // 针对你特定的编辑器实现
    };

    // 在编辑器字段附近显示“正确”图标(对勾)的钩子。
    // `iconElement` 是 Baton 提供的 DOM 元素(图标)。
    // 如果成功则返回 true,否则返回 false。
    Baton.AI.setEditorFieldCorrectHook = function (fieldId, iconElement) {
        // 例如针对 'MyEditor':
        // if (window.MyEditor && typeof window.MyEditor.getInstance === 'function') {
        //   const editorInstance = window.MyEditor.getInstance(fieldId);
        //   if (editorInstance && editorInstance.getContainer()) {
        //     // 将 iconElement 插入到编辑器容器之后
        //     editorInstance.getContainer().parentNode.insertBefore(iconElement, editorInstance.getContainer().nextSibling);
        //     return true;
        //   }
        // }
        return false; // 针对你特定的编辑器实现
    };
})();
</script>
<script src="{% static 'baton/js_snippets/init_baton.js' %}"></script>

📄 页面检测

Baton 使用 location.pathname 上的正则表达式来识别当前的管理页面类型(例如 change_formchangelist)。你可以针对自定义 URL 进行自定义。在 init_baton.js 之前,在 admin/base_site.html 中定义 Baton.detectPageHook

{{ conf|json_script:"baton-config" }} {# 假设 conf 是传递给模板的 BATON 设置字典 #}
<script src="{% static 'baton/app/dist/baton.min.js' %}"></script>
<script>
(function () {
    Baton.detectPageHook = function (defaultDetectFn) {
        if (/newschange/.test(location.pathname)) { // 示例:自定义 URL 部分
            return 'change_form';
        }
        return defaultDetectFn(); // 回退到 Baton 的默认检测
    };
})();
</script>
<script src="{% static 'baton/js_snippets/init_baton.js' %}"></script>

可用页面类型: dashboardadmindocsloginlogoutpassword_changepassword_change_successadd_formchange_formchangelistfilerdefault

📡 信号

Baton 使用其调度器发出 JavaScript 事件。请在 Baton.init() 之前注册监听器。

<script>
(function ($) { // 通过 Baton 可以使用 $ 表示 jQuery
    Baton.Dispatcher.register('onReady', function () { console.log('BATON 已就绪'); });
    Baton.Dispatcher.register('onMenuReady', function () { console.log('BATON 菜单已就绪'); });
    Baton.Dispatcher.register('onNavbarReady', function () { console.log('BATON 导航栏已就绪'); });
    Baton.Dispatcher.register('onTabsReady', function () { console.log('BATON 选项卡已就绪'); });
    Baton.Dispatcher.register('onTabChanged', function (evtName, tabData) { console.log('BATON 选项卡已更改', tabData); });
    Baton.Dispatcher.register('onMenuError', function () { console.error('BATON 菜单加载失败'); });
})(Baton.jQuery); // 传入 Baton 的 jQuery 实例
</script>
<script src="{% static 'baton/js_snippets/init_baton.js' %}"></script>

事件:

  • onReady:Baton JS 完全初始化。
  • onNavbarReady:导航栏渲染完成。
  • onMenuReady:菜单渲染完成(通常最后完成,因为是异步加载)。
  • onTabsReady:表单选项卡渲染完成。
  • onTabChanged:活动表单选项卡发生变化。
  • onMenuError:菜单内容加载失败。

🧩 JS 工具

Baton 导出 JS 模块,供你在自定义管理脚本中使用。

调度器

一个单例中介者模式的实现。

// 注册回调
Baton.Dispatcher.register('myCustomEvent', function (eventName, eventData) {
    console.log('事件 ' + eventName + ' 触发,数据为:', eventData);
});

// 发布事件
Baton.Dispatcher.emit('myCustomEvent', { message: '你好,Baton!' });

模态框

以编程方式创建 Bootstrap 模态框。 模态框截图

// 模态框配置对象示例:
// let config = {
//     title: '我的模态框标题',
//     subtitle: '我的副标题', // 可选
//     content: '<p>我的 HTML 内容</p>', // 替代 URL
//     url: '/my/url', // 通过 AJAX 获取内容;替代 content。
//     hideFooter: false, // 可选
//     showBackBtn: false, // 可选,显示返回按钮
//     backBtnCb: function () {}, // 可选,返回按钮点击回调
//     actionBtnLabel: '保存', // 可选,默认为 '保存'
//     actionBtnCb: null, // 可选,操作按钮回调
//     onUrlLoaded: function () {}, // 可选,AJAX 内容加载后的回调
//     size: 'lg', // 可选:sm、md、lg、xl
//     onClose: function () {} // 可选,模态框关闭时的回调
// };

let myModal = new Baton.Modal({
    title: '我的模态框标题',
    content: '<p>模态框主体的一些 HTML 内容。</p>',
    size: 'lg' // 示例尺寸
});

myModal.open();
// myModal.close();
// myModal.toggle();
// myModal.update({ title: '新的模态框标题', content: '<p>这里是更新的内容。</p>' });

🌐 JS 翻译

Baton 包含其 JS 消息的 enit 翻译版本。它会根据 <html> 标签的 lang 属性检测用户的语言环境。通过在调用 Baton.init() 之前定义 Baton.translations 来添加或覆盖翻译:

// 放在 admin/base_site.html 中,在 init_baton.js 之前
Baton.translations = {
  // 默认英文,可覆盖或添加其他语言
  en: {
    unsavedChangesAlert: '您有一些未保存的更改。',
    uploading: '上传中...',
    filter: '筛选',
    close: '关闭',
    save: '保存',
    search: '搜索',
    cannotCopyToClipboardMessage: '无法复制到剪贴板,请手动操作:Ctrl+C,Enter',
    retrieveDataError: '获取数据时出错',
    lightTheme: '浅色主题',
    darkTheme: '深色主题'
  },
  it: { // 意大利语示例
    unsavedChangesAlert: 'Ci sono modifiche non salvate.',
    uploading: 'Caricamento...',
    // ... 其他意大利语翻译
  }
  // 根据需要添加其他语言,例如 'es': { ... }
};

如果找不到用户语言环境的翻译,Baton 将默认使用 en

📊 列表筛选器

列表筛选器截图

文本输入筛选器

在您的 ModelAdmin 中创建文本输入筛选器。(改编自这篇文章)。

# admin.py
from baton.admin import InputFilter
from django.contrib import admin # 如果尚未导入

class MyModelIdFilter(InputFilter):
    parameter_name = 'id' # URL 查询参数
    title = 'ID'          # 筛选器的显示标题

    def queryset(self, request, queryset):
        if self.value() is not None:
            # 确保值被当作预期类型处理,例如 ID 应为整数
            try:
                search_term = int(self.value())
                return queryset.filter(id=search_term)
            except ValueError:
                return queryset.none() # 或者适当地处理错误
        return queryset

class MyModelAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'other_field') # 示例
    list_filter = (MyModelIdFilter, 'other_field')

下拉菜单筛选器

如果筛选器至少有 3 个选项,则提供标准 Django 管理界面列表筛选器的下拉菜单版本。(灵感来自 django-admin-list-filter-dropdown)。

Django 管理筛选器 Baton 对应版本
SimpleListFilter SimpleDropdownFilter
AllValuesFieldListFilter DropdownFilter
ChoicesFieldListFilter ChoicesDropdownFilter
RelatedFieldListFilter RelatedDropdownFilter
RelatedOnlyFieldListFilter RelatedOnlyDropdownFilter

使用方法:

# admin.py
from baton.admin import DropdownFilter、RelatedDropdownFilter、ChoicesDropdownFilter
# from myapp.models import MyModel、MyRelatedModel # 您的模型

class MyModelAdmin(admin.ModelAdmin):
    # list_display = ('name', 'char_field', 'choice_field', 'foreign_key_field') # 示例
    list_filter = (
        ('char_field', DropdownFilter), # 对于 CharField、TextField 等
        ('choice_field', ChoicesDropdownFilter), # 对于有选项的字段
        ('foreign_key_field', RelatedDropdownFilter), # 对于 ForeignKey、ManyToManyField
    )

多选筛选器

对某个字段的多个选项进行筛选。

# admin.py
from baton.admin import MultipleChoiceListFilter
# from myapp.models import News # 假设 News 模型有 Status 选项

class NewsStatusListFilter(MultipleChoiceListFilter):
    title = '状态'
    parameter_name = 'status__in' # 用于 __in 查找的查询参数

    def lookups(self, request, model_admin):
        # 示例,假设 News.Status 有 .choices 属性
        # return News.Status.choices
        return (('draft', '草稿'), ('published', '已发布'), ('archived', '已归档')) # 示例选项

class NewsAdmin(admin.ModelAdmin):
    # list_display = ('title', 'status') # 示例
    list_filter = (NewsStatusListFilter, 'publication_date')

更改列表包含

需要浏览器支持 HTML <template> 标签。

将自定义模板嵌入到更改列表页面中。

# admin.py
# from django.contrib import admin # 如果使用 @admin.register
# from myapp.models import News # 您的模型

# @admin.register(News)
class NewsAdmin(admin.ModelAdmin):
    # ...
    baton_cl_includes = [
        ('myapp/admin_includes/cl_top_banner.html', 'top'),
        ('myapp/admin_includes/cl_below_table.html', 'below'),
    ]

更改列表包含截图

位置:

位置 描述
top 在更改列表表单内部,顶部。
bottom 在更改列表表单内部,底部。
above 在整个更改列表表单上方。
below 在整个更改列表表单下方。

更改列表视图的上下文变量可在您包含的模板中使用。

对象工具栏包含: 将模板注入到对象工具栏(更改列表右上角)。模板会被注入到一个 <ul> 中。

# admin.py
class NewsAdmin(admin.ModelAdmin):
    # ...
    baton_cl_object_tools_include = ('myapp/admin_includes/custom_cl_action.html', 'left') # 或 'right'

更改列表筛选器包含

需要浏览器支持 HTML <template> 标签。

将自定义模板嵌入到更改列表筛选器容器中。

# admin.py
from baton.admin import FilterInclude
# from myapp.models import MyModel # 您的模型

class MyModelAdmin(admin.ModelAdmin):
    # ...
    baton_cl_filters_includes = [
        ('myapp/admin_includes/filter_top_banner.html', 'top'),
        ('myapp/admin_includes/filter_bottom_banner.html', 'bottom'),
    ]

更改列表筛选器包含截图

位置:

位置 描述
top 在筛选器容器内部,顶部。
bottom 在筛选器容器内部,底部。
above 在整个筛选器容器上方。
below 在整个筛选器容器下方。

更改列表视图的上下文变量可在您包含的模板中使用。

admin.py

class NewsAdmin(admin.ModelAdmin): # ... baton_cl_filters_includes = [ ('myapp/admin_includes/filters_top_custom_filter.html', 'top'), ('myapp/admin_includes/filters_bottom_info.html', 'bottom'), ]


![更改列表筛选器包含截图](https://oss.gittoolsai.com/images/otto-torino_django-baton_readme_d6de53a6b450.png)

**位置:**

| 位置 | 描述                                          |
| :------- | :--------------------------------------------------- |
| `top`    | 在筛选器容器内,位于顶部。                 |
| `bottom` | 在筛选器容器内,位于底部。              |

更改列表视图的上下文变量可用。

## ↔️ <a name="changelist-row-attributes">更改列表行属性</a>
>
> 需要浏览器支持 HTML `<template>` 标签。

为更改列表表格中的元素(行、单元格)添加 HTML 属性(类、`data-*`、`title` 等)。
![更改列表行属性截图](https://oss.gittoolsai.com/images/otto-torino_django-baton_readme_758631c8cebb.png)

1. 在您的 `ModelAdmin` 中定义 `baton_cl_rows_attributes` 方法。它接受 `request` 和 `cl`(更改列表实例)作为参数。
2. 返回一个 JSON 字符串字典。键通常与实例 ID 匹配。值是指定属性和选择器的字典。

```python
# admin.py
import json
from django.utils.safestring import mark_safe
# from myapp.models import News # 假设 News 模型

class NewsAdmin(admin.ModelAdmin):
    list_display = ('title', 'get_category_display', 'status') # 使用方法名

    def get_category_display(self, instance):
        # 如果需要通过选择器定位特定单元格,可以使用此辅助函数
        if instance.category: # 检查类别是否存在
            return mark_safe(f'<span class="category-span-{instance.category.id}">{instance.category.name}</span>')
        return "-" # 如果没有类别,则显示“-”
    get_category_display.short_description = '类别'
    get_category_display.admin_order_field = 'category' # 可选:如果希望允许排序

    def baton_cl_rows_attributes(self, request, cl):
        data = {}
        # 示例 1:为类别 ID 为 2 的新闻条目行添加 'table-info' 类
        for news_item in cl.queryset.filter(category__id=2):
            data[str(news_item.id)] = { # 确保键为字符串以便转换为 JSON
                'class': 'table-info',
            }

        # 示例 2:更复杂的情况——为目标新闻条目的特定单元格设置样式
        # 此示例假设您希望为 ID 为 1 且 category_id 为 1 的新闻条目单元格设置样式
        try:
            news_to_style = cl.queryset.get(id=1, category__id=1) # 更具体的查询
            data[f"customkey_cell_{news_to_style.id}"] = { # 如果选择器足够具体,键可以是任意字符串
                'class': 'table-success font-weight-bold', # 示例:成功背景色加粗字体
                'data-category-name': news_to_style.category.name if news_to_style.category else '',
                'title': f'特别:{news_to_style.title}',
                # 此选择器用于定位由 get_category_display 创建的 span 元素
                # 它假定更改列表会在单元格中渲染 get_category_display 的输出
                'selector': f'#result_list tr input[name=_selected_action][value="{news_to_style.pk}"] ~ td .category-span-{news_to_style.category_id}',
                'getParent': 'td', # 将属性应用于找到的 span 元素的父级 <td>
            }
        except cl.model.DoesNotExist: # 或者您特定模型的 DoesNotExist 异常
            pass # 未找到该条目,或不符合条件

        return json.dumps(data)

返回字典值的规则:

  • 键: 通常是模型实例的主键(以字符串形式)。如果使用不依赖实例 ID 的自定义 selector,则键可以是任何唯一字符串。
  • selector(可选):用于查找目标元素的 CSS 选择器。
    • 默认值:'#result_list tr input[name=_selected_action][value="' + key + '"]'(指向实例 key 所在行的复选框)。此设置适用于启用“操作”功能时。
  • getParent(可选):
    • 默认值:'tr'(属性将应用于整行)。
    • 您也可以指定其他选择器(例如 'td''.field-my_field'),以找到由 selector 匹配元素的父级。
    • 设置为 false(布尔值,而非字符串)或空字符串,表示直接将属性应用于由 selector 匹配的元素。
  • 其他键: 被视为要添加到目标元素的 HTML 属性。

📑 表单选项卡

表单选项卡截图 使用选项卡组织管理后台表单中的字段集和内联表单。标题会自动派生。

配置(在 ModelAdmin.fieldsetsModelAdmin.inlines 中):

# admin.py
# from myapp.models import Attribute, Feature # 您的模型

# class AttributeInline(admin.StackedInline):
#     model = Attribute # 您的模型
#     extra = 1

# class FeatureInline(admin.StackedInline):
#     model = Feature # 您的模型

#     extra = 1

class ItemAdmin(admin.ModelAdmin):
    # list_display = ('label', 'description', 'main_feature')
    # inlines = [AttributeInline, FeatureInline] # 内联的顺序对分组很重要

    fieldsets = (
        ('主要信息', { # 这个字段集将成为第一个标签页(或其一部分)
            'fields': ('label', 'description'),
            'classes': ('baton-tabs-init', 'order-0', 'baton-tab-group-main--inline-attribute'),
            # 'baton-tabs-init':必须在第一个字段集中使用,以启用标签页功能。
            # 'order-X':(可选)定义该字段集的标签页顺序。默认为0。
            # 'baton-tab-inline-MODELNAME':为名为`MODELNAME`(小写模型名)的内联创建一个标签页。
            # 'baton-tab-fs-CUSTOMNAME':为该字段集创建一个标签页(例如,“Main Info” -> “content_tab”)。
            # 'baton-tab-group-GROUPNAME--item1type-ITEMNAME--item2type-ITEMNAME':创建一个分组标签页。
            #    GROUPNAME 是任意名称。ITEMNAME 可以是 fs-字段集名称 或 inline-内联模型名称。
            #    例如:“baton-tab-group-overview--fs-main_info--inline-attribute”
            #    这将创建一个名为“Overview”的分组标签页,包含“Main Info”字段集和“Attribute”内联。
            'description': '这是物品的主要信息。'
        }),
        ('内容详情', {
            'fields': ('text', ),
            'classes': ('baton-tab-fs-content', ), # 该字段集将成为名为“Content”的标签页
            'description': '物品的详细内容。'
        }),
        ('技术规格', {
            'fields': ('main_feature', ),
            # 该字段集属于“Main Info”字段集中定义的一个分组标签页:
            # 例如,“Main Info”中的‘baton-tab-group-main--inline-attribute--fs-tech--inline-feature’会将其归入该分组。
            'classes': ('baton-tab-fs-tech', ),
            'description': '技术规格和特性。'
        }),
    )

标签页类别的规则(应用于字段集的 classes 元组):

  • baton-tabs-init:必须在第一个字段集定义中使用,以激活标签页系统。
  • order-X:(可选,在第一个字段集中使用)设置由第一个字段集生成的标签页的显示顺序。X 是一个数字(如 order-0order-1)。
  • baton-tab-inline-MODELNAME:为模型名为 MODELNAME(小写)的内联创建一个单独的标签页。如果内联使用了 related_name,则应使用 baton-tab-inline-RELATEDNAME
  • baton-tab-fs-CUSTOMNAME:为同时具有 tab-fs-CUSTOMNAME 类别的字段集创建一个单独的标签页。CUSTOMNAME 是您选择的任意名称。
  • baton-tab-group-GROUPNAME--item1type-ITEM1NAME--item2type-ITEM2NAME...:创建一个分组标签页。
    • GROUPNAME 是您为标签页选择的任意名称。
    • itemXtype 可以是 fs(用于字段集)或 inline(用于内联)。
    • ITEMXNAME 是您的 CUSTOMNAME(用于字段集)或 MODELNAME/RELATEDNAME(用于内联)。
    • 例如:baton-tab-group-overview--fs-main_content--inline-attributes
  • 没有 baton-tab-fs-* 类别且不属于任何分组的字段集,将被附加到第一个标签页上。
  • 若要使某个字段集始终可见(不隶属于任何标签页),请为其添加 tab-fs-none 类别。

其他标签页功能:

  • 如果表单字段出现错误,包含该字段的第一个标签页将自动打开。
  • 通过在 URL 中添加标签页的哈希值来实现深度链接(如 #inline-feature#fs-content#group-overview--fs-main_content--inline-attributes)。哈希值源自标签页类别的名称。

📎 表单包含

需要浏览器支持 HTML <template> 标签。

在更改表单中特定字段附近嵌入自定义模板。

# admin.py
class NewsAdmin(admin.ModelAdmin):
    # ...
    baton_form_includes = [
        ('myapp/admin_includes/datetime_helper.html', 'publication_date', 'top'),
        ('myapp/admin_includes/content_notes.html', 'body_content', 'above'),
        ('myapp/admin_includes/field_icon.html', 'title', 'right'),
    ]

表单包含截图

位置:

位置 描述
top 在字段所在行的顶部。
bottom 在字段所在行的底部。
above 在字段所在行的上方。
below 在字段所在行的下方。
right 在输入框右侧的行内位置。

您的包含模板中可以访问 {{ original }} 对象(模型实例)。此功能与标签页兼容。

对象工具包含: 将模板注入到对象工具栏中(更改表单右上角)。模板会被插入到 <ul> 标签内。

# admin.py
class NewsAdmin(admin.ModelAdmin):
    # ...
    baton_form_object_tools_include = ('myapp/admin_includes/custom_object_action.html', 'left') # 或 'right'

对象工具包含截图

🤏 可折叠堆叠式内联

可折叠堆叠式内联截图 使 admin.StackedInline 中的每个条目都可以折叠。

在内联的 classes 中添加 collapse-entry

# admin.py
class VideoInline(admin.StackedInline):
    # model = Video # 您的模型
    extra = 1
    classes = ('collapse-entry', ) # 可以与 Django 的 'collapse' 类结合使用

若要使第一条目默认展开:

# admin.py
class VideoInline(admin.StackedInline):
    # model = Video # 您的模型
    extra = 1
    classes = ('collapse-entry', 'expand-first')

🎨 主题与自定义

轻松自定义 Baton 的外观:

  1. CSS 变量: 在你的应用的某个静态目录中创建一个 baton/css/root.css 文件(确保该应用在 INSTALLED_APPS位于 baton 之前)。覆盖 Baton 默认 root.css 中定义的任何 CSS 变量。 示例:

    /* myapp/static/baton/css/root.css */
    :root {
      --bs-primary: #FF6347;
      --bs-primary-rgb: 255,99,71;
      --baton-sidebar-active-bg: #FF6347;
    }
    
  2. 管理界面主题: 直接从管理站点的 /admin/baton/batontheme/ 创建和管理主题。每次只能激活一个主题。其 CSS 内容(应定义 CSS 变量)将覆盖 baton/css/root.css 文件。

    注意: 主题内容被标记为安全,并原样注入。请务必小心。 ✨ 你可以在 django-baton-themes 找到现成的主题。

  3. 深度自定义(重新编译 JS 应用程序): 如果需要更改 Bootstrap 的主色或辅色,或者进行大量修改,你可以重新编译 Baton 的 JavaScript 应用程序。 自定义截图

    1. 克隆 django-baton
    2. 导航到 django-baton/baton/static/baton/app/
    3. 运行 npm install
    4. 编辑 src/styles/_variables.scss(以及根据需要编辑其他 SCSS/JS 文件)。
    5. 运行 npm run compile
    6. 将编译后的 dist/baton.min.js 复制到你的项目中:YOUR_APP/static/baton/app/dist/
    7. 确保 YOUR_APPINSTALLED_APPS位于 baton 之前。

    对于支持自动重新编译的实时开发:

    1. cd django-baton/baton/static/baton/app/

    2. 运行 npm run dev:baton(启动 Webpack 开发服务器,默认在 http://localhost:8080)。

    3. 在你项目的 admin/base_site.html 中(可能需要覆盖),将脚本源更改为指向开发服务器:

      {# <script src="{% static 'baton/app/dist/baton.min.js' %}"></script> #}
      <script src="http://localhost:8080/static/baton/app/dist/baton.min.js"></script>
      

    现在,JS 应用程序中的更改会自动更新,只需刷新你的 Django 管理页面即可。

🧪 测试

Baton 包含使用 Selenium 的单元测试和端到端测试。要运行端到端测试,请确保测试应用(位于 Baton 仓库的 testapp 目录中)正在 localhost:8000 上运行。

💻 开发

要参与贡献或进行本地开发:

  1. 设置测试应用:

    cd testapp
    python3 -m venv .virtualenv
    source .virtualenv/bin/activate # Windows 上:.virtualenv\\Scripts\\activate
    cd app
    pip install -r requirements.txt
    python manage.py migrate
    python manage.py createsuperuser # 如需
    python manage.py runserver
    

    createsuperuser 后的默认登录信息:admin / admin,或你所设定的用户名和密码)。

  2. 启用开发时的实时 JS 重新编译:

    • testapp/app/templates/admin/base_site.html 中,将脚本源切换为 Webpack 开发服务器:

      {# <script src="{% static 'baton/app/dist/baton.min.js' %}"></script> #}
      <script src="http://localhost:8080/static/baton/app/dist/baton.min.js"></script>
      
    • 在一个新的终端中,导航到 Baton 的前端应用目录并启动开发服务器:

      cd /path/to/your/django-baton/baton/static/baton/app/
      npm install
      npm run dev # 用于持续开发,监听文件变化
      

    现在,对 Baton 前端应用的更改将会自动重新编译。刷新浏览器即可看到效果。

命令

在你的 Python 环境中安装 invokesphinx_rtd_theme 以生成文档:

pip install invoke sphinx_rtd_theme

要在本地生成文档(从 django-baton 仓库的根目录):

invoke docs

🤝 贡献

请阅读 CONTRIBUTING.md,了解我们的行为准则以及提交拉取请求的流程。我们欢迎所有贡献!

🌟 星标历史

星标历史图表

版本历史

5.1.22026/02/22
5.1.12026/02/11
5.1.02026/01/24
5.0.62026/01/21
5.0.52026/01/07
5.0.42026/01/07
5.0.32025/11/03
5.0.22025/06/11
5.0.12025/06/11
5.0.02025/06/03
4.2.32025/05/21
4.2.22024/12/12
4.2.12024/12/11
4.2.02024/12/02
4.1.02024/07/19
4.0.12024/06/12
3.1.02024/02/21
3.0.22024/02/01
3.0.12024/02/01
3.0.02024/01/31

常见问题

相似工具推荐

openclaw

OpenClaw 是一款专为个人打造的本地化 AI 助手,旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚,能够直接接入你日常使用的各类通讯渠道,包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息,OpenClaw 都能即时响应,甚至支持在 macOS、iOS 和 Android 设备上进行语音交互,并提供实时的画布渲染功能供你操控。 这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地,用户无需依赖云端服务即可享受快速、私密的智能辅助,真正实现了“你的数据,你做主”。其独特的技术亮点在于强大的网关架构,将控制平面与核心助手分离,确保跨平台通信的流畅性与扩展性。 OpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者,以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力(支持 macOS、Linux 及 Windows WSL2),即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你

349.3k|★★★☆☆|1周前
Agent开发框架图像

stable-diffusion-webui

stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面,旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点,将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。 无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师,还是想要深入探索模型潜力的开发者与研究人员,都能从中获益。其核心亮点在于极高的功能丰富度:不仅支持文生图、图生图、局部重绘(Inpainting)和外绘(Outpainting)等基础模式,还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外,它内置了 GFPGAN 和 CodeFormer 等人脸修复工具,支持多种神经网络放大算法,并允许用户通过插件系统无限扩展能力。即使是显存有限的设备,stable-diffusion-webui 也提供了相应的优化选项,让高质量的 AI 艺术创作变得触手可及。

162.1k|★★★☆☆|1周前
开发框架图像Agent

everything-claude-code

everything-claude-code 是一套专为 AI 编程助手(如 Claude Code、Codex、Cursor 等)打造的高性能优化系统。它不仅仅是一组配置文件,而是一个经过长期实战打磨的完整框架,旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。 通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能,everything-claude-code 能显著提升 AI 在复杂任务中的表现,帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略,使得模型响应更快、成本更低,同时有效防御潜在的攻击向量。 这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库,还是需要 AI 协助进行安全审计与自动化测试,everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目,它融合了多语言支持与丰富的实战钩子(hooks),让 AI 真正成长为懂上

160.4k|★★☆☆☆|今天
开发框架Agent语言模型

opencode

OpenCode 是一款开源的 AI 编程助手(Coding Agent),旨在像一位智能搭档一样融入您的开发流程。它不仅仅是一个代码补全插件,而是一个能够理解项目上下文、自主规划任务并执行复杂编码操作的智能体。无论是生成全新功能、重构现有代码,还是排查难以定位的 Bug,OpenCode 都能通过自然语言交互高效完成,显著减少开发者在重复性劳动和上下文切换上的时间消耗。 这款工具专为软件开发者、工程师及技术研究人员设计,特别适合希望利用大模型能力来提升编码效率、加速原型开发或处理遗留代码维护的专业人群。其核心亮点在于完全开源的架构,这意味着用户可以审查代码逻辑、自定义行为策略,甚至私有化部署以保障数据安全,彻底打破了传统闭源 AI 助手的“黑盒”限制。 在技术体验上,OpenCode 提供了灵活的终端界面(Terminal UI)和正在测试中的桌面应用程序,支持 macOS、Windows 及 Linux 全平台。它兼容多种包管理工具,安装便捷,并能无缝集成到现有的开发环境中。无论您是追求极致控制权的资深极客,还是渴望提升产出的独立开发者,OpenCode 都提供了一个透明、可信

144.3k|★☆☆☆☆|2天前
Agent插件

ComfyUI

ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎,专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式,采用直观的节点式流程图界面,让用户通过连接不同的功能模块即可构建个性化的生成管线。 这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景,也能自由组合模型、调整参数并实时预览效果,轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性,不仅支持 Windows、macOS 和 Linux 全平台,还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构,并率先支持 SDXL、Flux、SD3 等前沿模型。 无论是希望深入探索算法潜力的研究人员和开发者,还是追求极致创作自由度的设计师与资深 AI 绘画爱好者,ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能,使其成为当前最灵活、生态最丰富的开源扩散模型工具之一,帮助用户将创意高效转化为现实。

109.2k|★★☆☆☆|今天
开发框架图像Agent

gemini-cli

gemini-cli 是一款由谷歌推出的开源 AI 命令行工具,它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言,它提供了一条从输入提示词到获取模型响应的最短路径,无需切换窗口即可享受智能辅助。 这款工具主要解决了开发过程中频繁上下文切换的痛点,让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用,还是执行复杂的 Git 操作,gemini-cli 都能通过自然语言指令高效处理。 它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口,具备出色的逻辑推理能力;内置 Google 搜索、文件操作及 Shell 命令执行等实用工具;更独特的是,它支持 MCP(模型上下文协议),允许用户灵活扩展自定义集成,连接如图像生成等外部能力。此外,个人谷歌账号即可享受免费的额度支持,且项目基于 Apache 2.0 协议完全开源,是提升终端工作效率的理想助手。

100.8k|★★☆☆☆|1周前
插件Agent图像