且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

当已经有ID字段时,如何使UUID字段成为默认字段

更新时间:2022-12-05 17:20:58

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

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