数据已经存在于数据库中后添加了UUID字段。有没有办法为现有数据填充UUID字段?

时间:2012-09-18 02:33:09

标签: python django django-models django-south

我已经为我的一些模型添加了一个UUID字段,然后与South一起迁移。我创建的任何新对象都正确填充了UUID字段。但是,我所有旧数据的UUID字段都为空。

有没有办法为现有数据填充UUID数据?

3 个答案:

答案 0 :(得分:19)

对于以下示例类:

from django_extensions.db.fields import UUIDField

def MyClass:
    uuid = UUIDField(editable=False, blank=True)
    name = models.CharField()

如果您使用的是South,请创建数据迁移:

python ./manage.py datamigration <appname> --auto

然后使用以下代码使用特定逻辑更新迁移以添加UUID:

from django_extensions.utils import uuid

def forwards(self, orm):
    for item in orm['mypp.myclass'].objects.all():
        if not item.uuid:
            item.uuid = uuid.uuid4() #creates a random GUID
            item.save()


def backwards(self, orm):
    for item in orm['mypp.myclass'].objects.all():
        if item.uuid:
            item.uuid = None
            item.save()

您可以创建不同类型的UUID,每个UUID的生成方式不同。 uuid.py module in Django-extensions包含您可以创建的UUID类型的完整列表。

重要的是要注意,如果在具有大量对象的环境中运行此迁移,则可能会超时(例如,如果使用fabric进行部署)。生产环境将需要另一种填充现有字段的方法。

尝试对大量对象执行此操作时可能会耗尽内存(我们发现自己内存不足并且部署失败并且有17,000多个对象)。

要解决此问题,请在迁移中need to create a custom iterator(或将其粘贴到真正有用的位置,并在迁移中引用它)。它看起来像这样:

def queryset_iterator(queryset, chunksize=1000):
    import gc
    pk = 0
    last_pk = queryset.order_by('-pk')[0].pk
    queryset=queryset.order_by('pk')
    if queryset.count() < 1
        return []
    while pk < last_pk:
        for row in queryset.filter(pk__gt=pk)[:chunksize]:
            pk = row.pk
            yield row
        gc.collect()

然后您的迁移将变为如下所示:

class Migration(DataMigration):

    def forwards(self, orm):
        for item in queryset_iterator(orm['myapp.myclass'].objects.all()):
            if not item.uuid:
                item.uuid = uuid.uuid1()
                item.save()

    def backwards(self, orm):
        for item in queryset_iterator(orm['myapp.myclass'].objects.all()):
            if item.uuid:
                item.uuid = None
                item.save()

答案 1 :(得分:6)

要首先将UUID值添加到所有现有记录,您需要确保您的模型的UUID已归档为blank=True, null=True

然后使用south运行schemamigration命令,然后打开生成的迁移文件。 然后使用以下内容编辑您的迁移文件,如post

所示

引用:

  

您需要导入以下导入uuid

     

在forwards()函数结束时添加以下def def forward(self,orm):

...
for a in MyModel.objects.all():
    a.uuid = u'' + str(uuid.uuid1().hex)
    a.save()

如上所述,它将遍历现有实例并在迁移过程中向其添加uuid。

答案 2 :(得分:1)

Django文档中现在有一个excellent, updated answer for Django 1.9这个确切的问题。

节省了我很多时间!