Ответ 1
Для следующего образца класса:
from django_extensions.db.fields import UUIDField
def MyClass:
uuid = UUIDField(editable=False, blank=True)
name = models.CharField()
Если вы используете Юг, создайте миграцию данных:
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.py в Django-extensions содержит полный список типов UUID, которые вы можете создать.
Важно отметить, что если вы запускаете эту миграцию в среде с большим количеством объектов, у нее есть возможность тайм-аут (например, при использовании используемой ткани для развертывания). Альтернативный метод заполнения уже существующих полей будет необходим для производственных сред.
При попытке сделать это с большим количеством объектов возможно исчерпать память (у нас закончилось нехватка памяти и сбой развертывания с 17 000 + объектами).
Чтобы обойти это, вы должны создать пользовательский итератор в своей миграции (или придерживаться его там, где это действительно полезно, и ссылаться на это в вашей миграции). Он будет выглядеть примерно так:
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()