Django项目SQLite转MySQL迁移后页面JSON解码异常求助
问题背景
早期Django 3.2项目基于SQLite开发,团队通过插件创建的页面内容直接存储在数据库中。迁移至MySQL后,新页面正常,但旧页面在前端访问或后台复制粘贴时触发JSON解码错误,空白页面无此问题。推测是手动修改SQL转储文件时的引号处理逻辑导致存储的JSON格式损坏。
优化迁移方案(推荐用Django原生工具)
放弃手动修改SQL转储的方式,改用Django自带的dumpdata/loaddata工具,完全规避SQL语法差异问题:
导出SQLite数据为JSON
在原SQLite环境下执行:python manage.py dumpdata --exclude auth.permission --exclude contenttypes > db_dump.json排除
auth.permission和contenttypes是因为切换数据库后这些自动生成的权限和内容类型会重新创建,避免冲突。配置MySQL并初始化数据库
修改Django的settings.py数据库配置为MySQL:DATABASES = { 'default': { 'ENGINE': 'django.db.backends.mysql', 'NAME': 'your_db_name', 'USER': 'root', 'PASSWORD': 'your_password', 'HOST': 'mysql_host', 'PORT': '3306', 'OPTIONS': { 'charset': 'utf8mb4', }, } }执行数据库迁移初始化表结构:
python manage.py migrate导入JSON数据到MySQL
python manage.py loaddata db_dump.json
手动修改SQL转储的优化步骤(若坚持用此方式)
如果必须手动处理SQL转储,核心是区分DDL语句的标识符引号和INSERT数据的字符串引号,避免破坏存储的JSON内容:
生成SQL转储
sqlite3 data/db.sqlite3 .dump > dump.sql清理SQLite特定语法
- 删除
PRAGMA foreign_keys=OFF;行 - 将
BEGIN TRANSACTION;替换为BEGIN; - 将
AUTOINCREMENT替换为AUTO_INCREMENT - 删除所有包含
sqlite_sequence的行
- 删除
精准替换标识符引号
只替换CREATE TABLE/CREATE INDEX等DDL语句中表名、字段名的双引号为反引号,不要替换INSERT语句里的字符串值:sed -i '/^CREATE/{s/"/`/g}' dump.sql处理索引名称长度
MySQL要求索引名不超过64字符,对过长的索引名手动修改,例如:
将CREATE UNIQUE INDEX "some_very_long_index_name_on_table_column" ON "table" ("column");
修改为:CREATE UNIQUE INDEX `idx_table_column_unique` ON `table` (`column`);导入MySQL
mysql -u root -p"your_password" your_db_name < dump.sql
JSON解码错误的针对性修复
如果已经完成迁移但出现错误,可直接修复数据库中损坏的JSON内容:
检查并修复字段内容
假设存储页面内容的表为page,字段为content,执行SQL替换错误的引号:UPDATE `page` SET `content` = REPLACE(`content`, '`', '"');注意:执行前务必备份数据,避免不可逆修改。
Django Shell批量验证修复
通过Django shell批量验证并修复JSON格式:import json from your_app.models import Page for page in Page.objects.all(): if not page.content: continue # 替换错误的引号 fixed_content = page.content.replace('`', '"') try: # 验证JSON合法性 json.loads(fixed_content) page.content = fixed_content page.save() print(f"修复成功:页面ID {page.id}") except json.JSONDecodeError as e: print(f"页面ID {page.id} 修复失败:{str(e)}")
验证方法
- 在Django shell中读取页面内容,尝试解析JSON,确认无解码错误
- 访问前端页面,测试页面展示和后台复制粘贴功能
内容的提问来源于stack exchange,提问作者Jerrod

