问题描述
我正在 Django 中重建一个个人项目(家谱),并且我正在努力将实际数据从旧的笨拙数据库迁移到我的新模型/模式,两个 Postgres 数据库。我已经在 settings.py 的 DATABASES 列表中将它们定义为“默认”和“源”。
我已经制作了我的模型,我想将旧数据库中的记录复制到新数据库中相应的表中,但我不太了解如何设置模型使其工作,因为Django 代码使用模型/ORM 来访问/更新/创建对象,我只有反映新模式的模型,而不是旧模式。
在一个巧合的情况下,我在旧数据库和新数据库中有一个具有完全相同架构的表,我有一个管理命令可以使用我的新 ImagePerson 模型 (ported_data = ImagePerson.objects.using('source').all()
) 从源中获取旧记录,因为它的预期字段是相同的。然后我在“默认”中为它们保存对象:(obj,created_bool) = ImagePerson.objects.using('default').get_or_create(field=fieldvalue,etc)
,它就像我需要的那样工作。
但是当我的表中旧版本缺少新模型/表具有的字段时,我无法使用该模型访问这些记录(这是有道理的)。我是否还应该为每个模型制作某种遗留版本以用于迁移?我看到一个教程提到运行 ./manage.py inspectdb --database=source > models.py
,但这样做似乎没有向我的文件添加任何其他内容(无论如何在那里保存临时/遗留模型似乎很奇怪)。访问旧格式记录的正确方法是什么? ORM 对吗?
举一个具体的例子,我有一个 Notes 表来保存关于特定人或特定家庭的记忆。旧表使用“类型”字段(1 用于个人注释,2 用于家庭注释)和一个 ref_id,它将是注释适用的个人或家庭的 id。新表改为有一个 person_id 字段和一个 family_id 字段。
我希望我的管理命令能够从源表中拉取所有记录,然后如果type=1,查找id等于ref_id字段的人,并在新数据库中保存一个新对象和那个人。我可以使用带有旧数据库的新 Notes 模型来获取它们,如下所示:ported_notes = Note.objects.using('source').all()
,但是如果我尝试访问任何字段(例如 print(note_row.body)
),我会收到一个错误,提示结果对象丢失person_id 字段
django.db.utils.ProgrammingError: column notes.person_id does not exist
解决方法
为旧模式创建模型显然不是正确的方法。
一种解决方案是编写数据迁移,您可以在其中使用原始 SQL 获取旧数据,然后使用 ORW 将其写入新表/模型:
from django.db import migrations,connections
def transfer_data(apps,schema_editor):
ModelForNewDB = apps.get_model('yourappname','ModelForNewDB')
# Fetch your old data
with connections['my_old_db'].cursor() as cursor:
cursor.execute('select * from some_table')
data = cursor.fetchall()
# Write it to your new models
for datum in data:
# do something with the data / add any
# additional values needed.
ModelForNewDB.objects.create(...)
class Migration(migrations.Migration):
dependencies = [
('yourappname','0001_initial'),]
operations = [
migrations.RunPython(transfer_data),]
然后只需运行您的迁移。但是需要注意一件事:
如果你在表之间有外键等,你需要小心你如何订购迁移。这可以通过编辑您的 dependencies
来完成。您甚至可能需要添加迁移以允许某些外键为空值,然后再添加另一个以纠正此问题。