Django:使用一个数据库填充另一个数据库的模型设置

Django: models setup for using one database to populate another

我正在用 Django 重建一个个人项目(家谱),我正在努力将实际数据从旧的笨拙的数据库迁移到我的新 model/schema,两个 Postgres 数据库。我在 settings.py 上的 DATABASES 列表中将它们定义为 'default' 和 'source'.

我已经制作了模型,我想将旧数据库中的记录复制到新数据库中相应的 table,但我不太了解如何设置模型让它工作,因为 Django 代码使用 models/ORM 到 access/update/create 对象,而且我只有反映新模式的模型,而不是旧模式。

在巧合的情况下,我有一个 table 在新旧数据库中具有完全相同的模式,我有一个管理命令可以使用我的新 ImagePerson 模型从源中获取旧记录( ported_data = ImagePerson.objects.using('source').all()), 因为预期的字段是相同的。然后我在 'default': (obj, created_bool) = ImagePerson.objects.using('default').get_or_create(field=fieldvalue, etc) 中为他们保存对象,它就像我需要的那样工作。

但是 当我有一个 table 时,旧版本缺少我的新 model/table 具有的字段,我无法使用该模型来访问这些记录(这是有道理的)。我是否还应该为每个模型制作某种遗留版本以用于迁移?我看到一个教程提到 运行 ./manage.py inspectdb --database=source > models.py,但这样做似乎并没有向我的文件中添加任何其他内容(无论如何将 temporary/legacy 模型保存在那里似乎很奇怪)。访问旧格式记录的正确方法是什么? ORM 对吗?

举个具体的例子,我有一个笔记table,用来保存关于一个特定的人或一个特定的家庭的记忆。旧的 table 使用 'type' 字段(1 用于个人注释,2 用于家庭注释),以及一个 ref_id 作为注释适用的个人或家庭的 ID .新的 table 有一个 person_id 字段和一个 family_id 字段。

我希望我的管理命令能够从源 table 中提取所有记录,然后如果 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 将其写入新的 tables/models:

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 来完成。您甚至可能需要添加迁移以允许某些外键为空值,然后再添加一个迁移来更正此问题。