Django-filer迁移MySQL到PostgreSQL遇PolymorphicTypeInvalid错误及图片迁移求助
问题描述
我在Django应用中使用django-filer处理图片上传,尝试将数据从MySQL迁移到PostgreSQL时,用以下命令完成了导出与导入:
python manage.py dumpdata myapp> myapp.json set DJANGO_SETTINGS_MODULE=myproject.settings.production python manage.py loaddata "myapp.json"
数据已在pgAdmin4中确认导入成功,但打开含图片的页面或后台时触发内部服务器错误,错误信息示例:
PolymorphicTypeInvalid at /myapp/homepage ContentType 37 for <class 'django_comments_xtd.models.BlackListedDomain'> #205 does not point to a subclass!
或:
PolymorphicTypeInvalid at /admin/myapp/articles/30/change/ ContentType 37 for <class 'django_comments_xtd.models.BlackListedDomain'> #232 does not point to a subclass!
需要解决上述错误,并完成django-filer图片路径的迁移。
一、解决PolymorphicTypeInvalid错误
该错误源于django-polymorphic依赖的ContentType ID在MySQL与PostgreSQL中不匹配——dumpdata导出的JSON携带了旧数据库的ContentType ID,导入新库后无法对应正确的类型。
解决步骤:
重新导出数据(排除ContentType相关数据)
修改导出命令,避免导出contenttypes和依赖它的auth.permission,防止旧ID干扰新库:python manage.py dumpdata myapp --exclude contenttypes --exclude auth.permission > myapp.json修复已导入的错误数据
如果已经导入了旧数据,手动更新错误的ContentType关联:- 进入Django Shell:
python manage.py shell - 执行以下代码替换错误的ContentType ID(将示例中的
37和模型替换为实际错误信息中的内容):from django.contrib.contenttypes.models import ContentType from django_comments_xtd.models import BlackListedDomain # 获取当前库中正确的ContentType correct_ct = ContentType.objects.get_for_model(BlackListedDomain) # 更新所有关联错误ContentType的实例 BlackListedDomain.objects.filter(content_type_id=37).update(content_type=correct_ct)
- 进入Django Shell:
重新导入数据
若之前导入的数据存在大量错误,可先删除对应数据,再用修改后的导出文件重新执行loaddata命令。
二、django-filer图片路径迁移
django-filer的图片文件存储在文件系统中,数据库仅保存路径信息,迁移需同步文件并验证路径正确性:
操作步骤:
同步文件系统
将原MySQL环境MEDIA_ROOT目录下的所有文件(含django-filer的图片、缩略图)完整复制到PostgreSQL环境的MEDIA_ROOT目录,保持目录结构完全一致。修正数据库中的文件路径
如果旧库中存储的是绝对路径,需批量更新为新环境的路径:- 进入Django Shell:
python manage.py shell - 执行路径替换(将示例中的旧路径和新路径替换为实际路径):
from django.db.models import Value, Replace from filer.models import Image, File # 替换图片表中的路径 Image.objects.update(file=Replace('file', Value('/old/media/path/'), Value('/new/media/path/'))) # 替换文件表中的路径 File.objects.update(file=Replace('file', Value('/old/media/path/'), Value('/new/media/path/')))
若存储的是相对路径,文件同步完成后无需修改。
- 进入Django Shell:
重建缩略图缓存
重新生成缩略图以适配新环境:# 清理孤立文件 python manage.py filer_purge_orphaned_files # 重新生成所有缩略图 python manage.py filer_generate_thumbnails
内容的提问来源于stack exchange,提问作者Adrian

