Поле UUID добавлено после данных уже в базе данных. Есть ли способ заполнить поле UUID для существующих данных?

Я добавил поле UUID в некоторые из моих моделей, а затем перешел на юг. Любые новые объекты, которые я создаю, имеют поле UUID, заполненное правильно. Однако поля UUID во всех моих старых данных равны нулю.

Есть ли способ заполнить данные UUID для существующих данных?

3 Solutions collect form web for “Поле UUID добавлено после данных уже в базе данных. Есть ли способ заполнить поле UUID для существующих данных?”

Для следующего образца класса:

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() 

Чтобы сначала добавить значения UUID ко всем существующим записям, вам нужно убедиться, что ваша модель имеет UUID с blank=True, null=True

Затем запустите команду schemamigration с юга и затем откройте полученный файл миграции. Затем отредактируйте файл миграции следующим образом, как показано в этом сообщении.

Цитата:

Вам нужно будет импортировать следующий импорт uuid

В конце функции forward () добавьте следующие def forward (self, orm):

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

Как указано, будет проходить через существующие экземпляры и добавлять к нему uuid как часть миграции.

Теперь в Django 1.9 есть отличный, обновленный ответ на этот точный вопрос в документах Django.

Сэкономил мне много времени!

Python - лучший язык программирования в мире.