一部のモデルにUUIDフィールドを追加してから、Southに移行しました。私が作成する新しいオブジェクトには、UUIDフィールドが正しく入力されています。ただし、古いデータすべてのUUIDフィールドはnullです。
既存のデータのUUIDデータを入力する方法はありますか?
一部のモデルにUUIDフィールドを追加してから、Southに移行しました。私が作成する新しいオブジェクトには、UUIDフィールドが正しく入力されています。ただし、古いデータすべてのUUIDフィールドはnullです。
既存のデータのUUIDデータを入力する方法はありますか?
次のサンプルクラスの場合:
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を作成でき、それぞれが異なる方法で生成されます。Django-extensionsのuuid.pyモジュールには、作成できる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コマンドをsouthで実行し、結果の移行ファイルを開きます。次に、この投稿に示すように、次のように移行ファイルを編集します
引用:
次のインポートuuidをインポートする必要があります
forwards()関数の最後に、次のdef forwards(self、orm)を追加します。
... for a in MyModel.objects.all(): a.uuid = u'' + str(uuid.uuid1().hex) a.save()
前述のように、既存のインスタンスをループし、移行の一部としてuuidを追加します。
Djangoのドキュメントには、この正確な質問に対するDjango1.9の優れた更新された回答があります。
たくさんの時間を節約できました!