sen*_*rle 5 python django postgresql
我正在将 Django 站点从 MySQL 迁移到 PostgreSQL。数据量并不大,所以我采取了一个非常简单的方法:我只是使用了内置的 Django序列化和反序列化例程来创建 JSON 记录,然后将它们加载到新实例中,循环遍历对象,并将每个对象保存到新数据库中。
这工作得很好,有一个小问题:加载所有记录后,我IntegrityError在加载旧记录后尝试添加新数据时遇到了一个问题。与 MySQL 自动增量 ID 字段等效的 Postgres 是一个串行字段,但是当显式指定 id 值时,串行字段的内部计数器不会增加。结果,Postgres 尝试从 1 开始对记录进行编号——已使用——导致违反约束。(这是 Django 中的一个已知问题,标记为wontfix。)
有很多与此相关的问题和答案,但似乎没有一个答案直接在 Django 的上下文中解决这个问题。这个答案给出了一个你需要运行来更新计数器的查询的例子,但我尽量避免在可能的情况下进行显式查询。我可以在保存之前简单地删除 ID 字段,让 Postgres 自己进行编号,但ForeignKey在这种情况下,有些引用会被破坏。其他一切都运行得很漂亮!
如果 Django 提供一个例程来智能地处理任何边缘情况,那就太好了。(这不会修复错误,但它可以让开发人员以一致且正确的方式解决它。)我们真的只需要使用原始查询来修复这个问题吗?看起来太野蛮了。
如果真的没有这样的例程,我将简单地执行以下操作,直接运行上面链接的答案中建议的查询。但在这种情况下,我有兴趣了解这种方法的任何潜在问题,或者有关我可能做错了什么的任何其他信息。例如,我是否应该修改记录以使用 UUID,正如这表明的那样?
这是原始方法(经过编辑以反映我实际完成的工作的简化版本)。这与Pere Picornell的答案非常接近,但他对我来说看起来更健壮。
table = model._meta.db_table
cur = connection.cursor()
cur.execute(
"SELECT setval('{}_id_seq', (SELECT max(id) FROM {}))".format(table, table)
)
Run Code Online (Sandbox Code Playgroud)
关于争论:我的案例是一次性迁移,我的决定是在完成每个表的迁移后立即运行此函数,尽管您可以在怀疑完整性可能被破坏的任何时候调用它。
def synchronize_last_sequence(model):
# Postgresql aut-increments (called sequences) don't update the 'last_id' value if you manually specify an ID.
# This sets the last incremented number to the last id
sequence_name = model._meta.db_table+"_"+model._meta.pk.name+"_seq"
with connections['default'].cursor() as cursor:
cursor.execute(
"SELECT setval('" + sequence_name + "', (SELECT max(" + model._meta.pk.name + ") FROM " +
model._meta.db_table + "))"
)
print("Last auto-incremental number for sequence "+sequence_name+" synchronized.")
Run Code Online (Sandbox Code Playgroud)
我使用您在问题中提出的 SQL 查询来完成此操作。找到你的帖子非常有用。谢谢你!
它应该适用于自定义 PK,但不适用于多字段 PK。
| 归档时间: |
|
| 查看次数: |
197 次 |
| 最近记录: |