如果已有ID字段,如何使UUID字段默认

时间:2018-01-11 04:58:51

标签: django python-3.x django-models django-rest-framework

我正在研究一个项目,问题是我已经创建了具有简单ID列的模型,但现在我的要求已经更改,我想用UUID字段替换ID字段(模型)我刚刚更新了我的模型:

uuid = models.UUIDField(primary_key=True, default=uuid.uuid4)

但是当我运行迁移时出现错误

  

django.db.utils.OperationalError:(1829,“不能删除列'id':   在外键约束中需要

请指导我如何执行此迁移?

1 个答案:

答案 0 :(得分:1)

以下是您需要执行的操作列表

1 - 将新的uuid字段添加到模型(我将此模型命名为Base),然后生成迁移文件

  

uuid = models.UUIDField(default = uuid4,blank = True,null = True)

  • 请注意,uuid还不是主键
  • 请注意blank = null =True

2-在此步骤中,您应该使用有效数据填充uuid字段。您应该为Base模型编写数据迁移文件。请查看docs以获取更多信息

你的前锋方法应该是这样的:

for item in Base.objects.all():
    item.uuid = uuid4()
    item.save()

3-将uuid字段更改为此并生成迁移

  

uuid = models.UUIDField(default = uuid4,unique = True)

  • 请注意,uuid还不是主键,但它现在是唯一的

4 - 对于指向Base模型的其他模型,您应该添加一个指向uuid字段的新外键

假设您对Base模型的默认关系是这样的

base = models.ForeignKey(
    Base, on_delete=models.PROTECT, related_name='base'
)

你应该像这样添加一个临时字段

base_uuid = models.ForeignKey(
    Base,
    on_delete=models.PROTECT,
    related_name='base_uuid',
    to_field='uuid',
    blank=True,
    null=True,
)
  • 请注意我已明确定义to_field告诉django此外键未指向默认pk字段
  • 你应该保留旧的外键字段
  • 还设置blank = null = True
  • 对于指向Base的所有foreignkeys / manytomanyfield,您应该添加此临时字段

5-在此步骤中,您应该创建一个数据迁移文件

在此数据迁移文件中,您需要使用有效数据(基于旧base_uuid字段)填充所有base字段,您的迁移代码可能是这样的

for item in RelatedModel.objects.all():
    item.base_uuid_id = item.base.uuid
  • 在此步骤之后,所有模型中的所有base_uuid字段都应包含有效数据

6-在所有相关模型中删除相关字段(保留新的base_uuid字段但丢弃旧的相关字段)并生成迁移文件

7- Base模型更改uuid字段并生成迁移文件

  

uuid = models.UUIDField(default = uuid4,primary_key = True)

  • uuid现在是主键!

8-在所有相关模型(已添加base_uuid个字段的模型)中更新字段

  • 重命名字段名称(从列名中删除_uuid
  • 更改relate_name字段名称(从相关名称中删除_uuid
  • 必要时删除blank = null = true
  • 删除to_field='uuid'参数(您不再需要它)

非常重要注意:使用测试数据运行这些代码,并在对实际数据运行此代码之前从数据库创建完整备份