Mealie v1 迁移指南:从旧版导出备份到新实例的完整实操与源码解析
【免费下载链接】mealieMealie is a self hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in Vue for a pleasant user experience for the whole family. Easily add recipes into your database by providing the url and mealie will automatically import the relevant data or add a family recipe with the UI editor项目地址: https://gitcode.com/GitHub_Trending/me/mealie
Mealie 的 v1 版本从底层重构了数据模型、API 与权限体系,旧版数据无法直接平滑升级。本文基于官方迁移文档,完整讲解"旧实例导出备份 → 新实例导入迁移 → 校验报告"的四步迁移路径,并深入剖析仓库内MealieAlphaMigrator迁移器的字段映射、报告机制与图片导入实现,帮助你安全、快速地把旧版食谱数据搬进 v1 实例。
迁移前必须了解的三件事
v1 发布版本应当被视为一个全新的应用:大量改动提升了应用性能与开发者体验,但也带来了无法回避的破坏性变更。在动手迁移之前,请先确认以下三点:
- API 集成将被破坏:v1 中多个 API 端点已经变化。如果你依赖旧版 API 编写了外部脚本或集成代码,必须改用新的端点。
- 食谱默认私有:v1 中食谱默认只能被登录用户查看。你可以精细配置公开访问,也可以让实例保持完全私有。详见权限与公开访问指南。
- 迁移支持范围有限:目前迁移工具只覆盖以下数据类型,其余类型(如用户、分组、饮食计划、Cookbook/页面)仍在开发中:
| 数据类型 | 迁移支持状态 |
|---|---|
| Recipes(食谱) | ✅ 已支持 |
| Categories(分类) | ✅ 已支持 |
| Tags(标签) | ✅ 已支持 |
| Users(用户) | ❌ 未支持 |
| Groups(分组) | ❌ 未支持 |
| Meal Plans(饮食计划) | ❌ 未支持 |
| Cookbooks / Pages(食谱簿/页面) | ❌ 未支持 |
官方说明:支持更多数据类型的工作正在推进中,但并非当前优先级,欢迎通过 PR 贡献额外数据的迁移支持。
Step 1:搭建全新 v1 实例
考虑到升级的本质,强烈建议在现有实例旁边并行搭建一个新的 v1 实例,而不是在旧实例上原地升级。这样可以安全、快速地进行数据迁移,且不会影响正在运行的旧服务。
按照安装清单完成新实例的搭建并成功登录后,再继续进入 Step 2。
从仓库结构看,v1 采用了docker-compose.yml、Dockerfile等标准的容器化部署方式,同时支持通过uv.lock与pyproject.toml管理 Python 依赖,新实例与旧实例可在不同端口/目录下并存运行。
Step 2:从 Pre-v1 旧实例导出数据
在旧版(pre-v1)实例中,进入Admin 管理后台,找到标记为"Backups"的区块(如上图所示),执行一次数据导出(备份)。
导出时请注意:
- 务必勾选包含食谱(recipes),这是迁移所需的核心数据;
- 勾选其他额外项目不会影响迁移流程,但即便包含它们也会被迁移器忽略(因为迁移器只解析食谱、分类与标签相关的数据);
- 导出产物是一个
.zip归档文件,请妥善保存。
从前端迁移页面展示的目录树(见 migrations.vue)可以确认,旧版备份包的内部结构大致如下:
mealie.zip └── recipes/ ├── recipe-name/ │ ├── recipe-name.json # 食谱元数据 │ └── images/ │ ├── original.webp │ ├── full.jpg │ └── thumb.jpg └── recipe-name-1/ ├── recipe-name-1.json └── images/ ...其中recipe-name.json为食谱数据文件,images目录存放该食谱的图片(原图、全尺寸图与缩略图)。
Step 3:使用迁移工具导入 v1 实例
在新 v1 实例中按以下步骤操作:
- 浏览器访问
/group/migrations页面; - 在迁移类型下拉框中选择 "Mealie"(即 pre-v1 迁移器,前端代码中映射为
mealie_alpha,见 migrations.vue); - 上传第 2 步从旧实例导出的
.zip备份文件; - 可选:勾选"为所有导入食谱添加迁移标签"选项,迁移器会自动为导入的食谱打上
mealie_alpha标签,便于事后识别与批量管理; - 点击提交,迁移随即开始。整个过程可能需要一些时间;
- 迁移完成后,页面下方的"Previous Migrations"(历史迁移)表格中会出现一条新记录,点击查看迁移报告,确认每条食谱的导入结果。
关于迁移报告:存在个别食谱导入失败的情况,但迁移器仍会继续导入其余成功的食谱。多数情况下,手动迁移失败食谱比排查失败原因更快。若迁移工具本身出现问题,可在 GitHub 上提交 issue 反馈。
迁移前端页面的实现细节
迁移页面(frontend/app/pages/group/migrations.vue)的界面元素与后端能力一一对应:
- 迁移类型下拉框支持 Mealie pre-v1 以及 Chowdown、CopyMeThat、MyRecipeBox、Nextcloud、Paprika、PlanToEat、RecipeKeeper、Tandoor、Cook'n 等十余种来源;
- Mealie 迁移只接受
.zip文件(acceptedFileType: ".zip"); - 页面上用树状视图直观展示备份包的期望结构,方便你对照检查导出的压缩包格式;
- 勾选"添加迁移标签"对应请求参数
addMigrationTag; - 提交后调用
api.groupMigration.startMigration(payload)触发后端POST /groups/migrations接口,返回的ReportSummary会插入到历史迁移列表顶部。
后端的迁移入口与执行流程
后端迁移接口由 GroupMigrationController 提供,路由为POST /groups/migrations,表单参数包括:
| 参数 | 类型 | 说明 |
|---|---|---|
archive | 文件(必填) | 上传的 zip 备份文件,服务端会先保存到临时目录 |
migration_type | 枚举(必填) | 迁移来源类型,如mealie_alpha |
add_migration_tag | 布尔(可选) | 是否给导入食谱添加来源标签,默认false |
控制器会根据migration_type从SupportedMigrations(见 group_migration.py)映射出对应的迁移器类,并传入当前登录用户、所在分组(group)与家庭(household)上下文,然后调用迁移器的migrate()方法。整个执行过程分为三步(见 BaseMigrator):
_create_report():在数据库中创建一条状态为in_progress的迁移报告;_migrate():执行实际的数据解析与导入(由各子类实现);_save_all_entries():将所有导入条目的成功/失败信息写入报告,并汇总出最终状态——全部成功为success、全部失败为failure、部分成功为partial。
MealieAlphaMigrator:旧版数据的字段映射与导入
MealieAlphaMigrator(mealie_alpha.py)是本次迁移的核心实现。它做了以下几件事:
字段别名映射:旧版 JSON 字段名与 v1 新 Schema 不一致,通过key_aliases完成转换:
| 旧字段(alias) | 新字段(key) | 处理函数 |
|---|---|---|
title | name | 无 |
ingredients | recipeIngredient | 无 |
directions | recipeInstructions | 无 |
tags | tags | split_by_comma(按逗号拆分、去除空白并转为首字母大写) |
Schema 归一化(_convert_to_new_schema):
categories→recipeCategory;- 删除旧版内部字段
_id、date_added; - 过滤掉 tags/categories 中的空字符串元素;
- 若
extras为列表则重置为空字典; - 将
comments置空列表; - 将
id重置为None,让数据库为新食谱生成全新主键。
压缩包解压与图片搬运(_migrate):迁移器将 zip 解压到临时目录,通过rglob("**/recipes/**/[!.]*.json")递归找出所有食谱 JSON 文件,逐个解析并导入数据库;导入成功后,再把原备份中该食谱images目录下的图片复制到新实例的食谱图片目录中。此外,BaseMigrator.get_zip_base_path还处理了 Safari 等工具解压产生的__MACOSX目录干扰,确保能正确定位备份包的根目录。
食谱所有者分配:执行任何迁移时,导入食谱的所有者会自动分配给执行迁移操作的用户。分组内的所有成员仍可访问该食谱,但所有者拥有特殊权限,可以锁定食谱、禁止其他用户编辑。这一逻辑在import_recipes_to_database中体现(见 _migration_base.py):每条食谱被写入user_id(当前用户)与group_id,标签与分类还会通过get_or_set_tags/get_or_set_category归并到分组现有的标签与分类体系中。
食谱默认设置的继承
迁移时,导入食谱的各项显示设置(是否公开、是否显示营养信息、是否显示素材、是否横向视图、是否禁用评论)并非硬编码,而是从当前家庭(household)的偏好设置中读取并应用到每条导入食谱上(见 _migration_base.py)。因此,导入前可以先在 v1 实例中配置好家庭偏好,迁移后的食谱会自动遵循这些默认值。
Step 4:迁移完成后的检查与收尾
迁移完成后,建议做以下检查:
- 查看迁移报告:确认每条食谱的状态(成功/失败),对失败条目决定是手动重建还是重新导入;
- 确认访问权限:由于 v1 食谱默认私有,请按需为公开食谱、分组或家庭配置公开访问。完整的判定规则(私有分组/家庭/食谱层层拦截、私密链接可绕过所有权限等)见权限与公开访问指南;
- 使用
mealie_alpha标签:如果勾选了迁移标签,可在食谱列表中按该标签筛选,快速复核导入结果或进行批量清理; - 体验 v1 新功能:v1 引入了大量新特性与改进,可通过项目的发布变更说明(仓库根目录的
cliff.toml即用于生成变更日志)了解每个版本的新增内容; - 确认新实例数据无误后,再逐步下线旧实例,完成整体切换。
常见问题与注意事项汇总
- 导出包包含食谱以外的数据怎么办?会被迁移器忽略,不影响迁移流程。
- 个别食谱导入失败怎么办?迁移报告会给出失败原因,其余成功食谱不受影响;官方建议直接手动重建失败的食谱,效率更高。
- 图片没有迁移成功?迁移器会尝试从备份的
images目录复制图片(见 migration_helpers.py 中的import_image/scrape_image),若源文件缺失或格式无法识别(UnidentifiedImageError),该食谱会保留但图片导入会被跳过并记录日志。 - 安全提示:迁移器对备份包内的图片路径做了目录穿越防护(
safe_local_path),任何试图逃逸解压根目录的路径都会被静默拒绝,避免归档文件触发任意本地文件读取。
通过以上四步,你可以把旧版 Mealie 的食谱、分类与标签数据完整搬入 v1 新实例,并在全新的权限体系与架构下继续使用。仓库中迁移相关的全部实现(迁移控制器、迁移基类、Mealie 迁移器)与前端页面(migrations.vue)均可直接查阅,作为理解或扩展迁移能力的参考。
【免费下载链接】mealieMealie is a self hosted recipe manager and meal planner with a RestAPI backend and a reactive frontend application built in Vue for a pleasant user experience for the whole family. Easily add recipes into your database by providing the url and mealie will automatically import the relevant data or add a family recipe with the UI editor项目地址: https://gitcode.com/GitHub_Trending/me/mealie
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考