当已经有ID字段时,如何使UUID字段成为默认字段 [英] How to make UUID field default when there's already ID field

查看:92
本文介绍了当已经有ID字段时,如何使UUID字段成为默认字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm working on a project and problem is I've already created models with simple ID column but now my requirements are changed and I want to replace ID field (model) with UUID field I just updated my model:

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

但是当我运行迁移时,我得到了一个错误

but when I run my migrations I got an error

django.db.utils.OperationalError :( 1829,无法删除列'id':外键约束中需要的

django.db.utils.OperationalError: (1829, "Cannot drop column 'id': needed in a foreign key constraint

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

Please guide me how can I perform this migration?

推荐答案

这是您需要执行的操作列表

here are the list of actions that you need to do

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

1 - add the new uuid field to model (I name this model Base) then generate migration files

uuid = models.UUIDField(默认= uuid4,空白=真,null =真)

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

  • 请注意,uuid还不是主键
  • 请注意, blank = null = True
  • 2-在此步骤中,应使用有效数据填充 uuid 字段.您应该为 Base 模型编写一个数据迁移文件.请查看文档以获取更多信息

    2- in this step you should populate uuid field with valid data. you should write a data migration file for Base model. please check docs for more info

    您的转发方法应如下所示:

    your forwards method should be something like this:

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

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

    3- change uuid field to this and generate migrations

    uuid = models.UUIDField(默认= uuid4,唯一=真)

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

    • 请注意,uuid尚不是主键,但现在是唯一的
    • 4-对于其他指向 Base 模型的模型,您应该添加一个指向uuid字段的新外键

      4 - for other models which are pointing to Base model you should add a new foreignkey pointing to uuid field

      假设您与基本模型的默认关系是这样的

      assumig your default relation to Base model is something like this

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

      您应该添加一个这样的临时字段

      you should add a temprory field like this

      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 的外键/manytomanyfield,您应添加此临时字段
        • note that I have explicitly defined to_field which tell django this foreign key is not pointing to default pk field
        • you should keep old foreign key field
        • also set blank = null = True
        • for all foreignkeys/manytomanyfield pointing to Base you should add this temp field
        • 5-在此步骤中,您应该创建一个数据迁移文件,

          5- in this step you should create a data migration file,

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

          in this data migration file you need to fill all base_uuid fields with valid data (based on old base field) your migration code can be something like this

          用于RelatedModel.objects.all()中的项目:item.base_uuid_id = item.base.uuid

          • 此步骤之后,所有模型中的所有 base_uuid 字段均应包含有效数据
            • after this step all base_uuid fields in all models should contain a valid data
            • 6-在所有相关模型中删除相关字段(保留新的 base_uuid 字段,但丢弃旧的相关字段)并生成迁移文件

              6- in all related models drop related field (keep the new base_uuid field but discard old related field) and generate a migration file

              7-删除所有FK字段上的db_constraint-这是必需的,因为django将通过 base_uuid 的唯一约束进行连接,如果将 uuid 更改为PK.

              7- delete the db_constraint on all FK fields - this is needed, because django will connect through the unique constraint from base_uuid which will be dropped if we change uuid to pk.

              base_uuid = models.ForeignKey(
                  Base,
                  on_delete=models.PROTECT,
                  related_name='base_uuid',
                  to_field='uuid',
                  blank=True,
                  null=True,
                  db_constraint=False
              )
              

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

              8- in Base model change uuid field and generate a migration file

              uuid = models.UUIDField(默认= uuid4,primary_key = True)

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

              • uuid现在是主键!
              • 9-在所有相关模型(已添加 base_uuid 字段的模型)中更新字段

                9- in all related models (models which you have added base_uuid fields) update the field

                • 重命名字段名称(从列名称中删除 _uuid )(将其设为单个迁移!)
                • 更改 relate_name 字段名称(从相关名称中删除 _uuid )
                • 如有必要,删除 blank = null = true
                • 删除 to_field ='uuid'参数(不再需要此参数)
                • rename field name (remove _uuid from column name) (make this a individual Migration!)
                • change relate_name field name (remove _uuid from related name)
                • remove blank = null = true if necessary
                • remove to_field='uuid' argument (you don't need that any more)

                非常重要的提示::在测试数据上运行这些代码并从数据库创建完整备份,然后再对实际数据运行此代码

                Very Important Note: run these code with test data and create a full backup from your database before running this code on your actual data

                这篇关于当已经有ID字段时,如何使UUID字段成为默认字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆