You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django新增带随机默认函数字段如何为旧对象生成唯一值?

问题原因

Django执行新增字段的迁移操作时,你传入的default回调函数只会在迁移启动时被调用1次,返回的同一个值会被批量赋值给所有已存在的旧数据行。只有后续新创建的对象,才会每次新增时调用default生成新值,这就是你所有旧数据字段值重复的原因。

解决步骤

总共需要执行3次迁移完成需求:

  1. 第一步:先将新增字段设置为允许空值,避免迁移时直接赋值
    修改models.py中字段定义:
class Subscription(models.Model):
    # ... 其他字段省略 ...
    uniqueSubscriptionId = models.CharField(max_length=30, null=True)

执行迁移命令生成第一个迁移文件:
python manage.py makemigrations
执行迁移:
python manage.py migrate
此时表中uniqueSubscriptionId字段已新增,所有旧数据该字段值为NULL。

  1. 第二步:创建自定义迁移文件,为所有旧数据逐个生成唯一值
    执行命令生成空迁移文件(将命令中的你的app名替换为你自己的Django app名称):
    python manage.py makemigrations 你的app名 --empty
    打开新生成的空迁移文件,修改内容如下:
from django.db import migrations
from django.utils.crypto import get_random_string

def generate_unique_ids(apps, schema_editor):
    # 注意此处不能直接导入你的Subscription模型,必须用apps.get_model获取迁移时的模型版本
    Subscription = apps.get_model('你的app名', 'Subscription')
    # 遍历所有旧数据,逐个生成唯一值并保存
    for sub in Subscription.objects.all():
        sub.uniqueSubscriptionId = get_random_string(20)
        sub.save()

class Migration(migrations.Migration):
    dependencies = [
        # 这里是自动生成的依赖,不用修改
        ('你的app名', '00xx_xxxxxx'),
    ]

    operations = [
        migrations.RunPython(generate_unique_ids),
    ]

保存后执行迁移:
python manage.py migrate
此时所有旧数据的uniqueSubscriptionId字段已经被赋值为唯一随机值。

  1. 第三步:将字段改回非空,设置默认值适配后续新增数据
    再次修改models.py中字段定义,恢复你原本的配置:
class Subscription(models.Model):
    # ... 其他字段省略 ...
    uniqueSubscriptionId = models.CharField(default=generateUniqueSubscription, max_length=30)

执行迁移命令生成第三个迁移文件,执行时如果弹出询问框,选择「为现有行设置一次性默认值」即可,此时字段会被改为非空,后续新增的对象会自动调用generateUniqueSubscription生成唯一值:
python manage.py makemigrations
python manage.py migrate

额外说明

如果你的表数据量非常大,遍历所有对象保存的操作会比较慢,可以改用Django的批量更新逻辑优化速度;如果该字段需要加唯一约束unique=True,请在第二步完成旧数据赋值之后,再在第三步修改字段时添加约束,避免迁移时报重复值错误。

内容的提问来源于stack exchange,提问作者Pranava Mohan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 20:15:01