2012-09-18 4 views
17

一部のモデルにUUIDフィールドを追加してから、Southに移行しました。作成する新しいオブジェクトには、UUIDフィールドが正しく設定されています。しかし、すべての古いデータのUUIDフィールドはnullです。データベースに既に存在するデータの後にUUIDフィールドが追加されました。既存のデータのUUIDフィールドに値を設定する方法はありますか?

既存のデータにUUIDデータを設定する方法はありますか?次のサンプルクラスの

答えて

19

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を作成できますntly。 uuid.py module in Django-extensionsには、作成できるUUIDの種類の完全なリストがあります。

オブジェクトの数が多い環境でこの移行を実行すると、タイムアウトする可能性があることに注意してください(たとえば、ファブリックを使用して配置する場合など)。実環境では、すでに存在するフィールドを埋める別の方法が必要になります。

多数のオブジェクトに対してこれを実行しようとしている間にメモリが不足する可能性があります(メモリが不足し、デプロイメントが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() 
+4

ダウンローダはこれを見ることはできませんが、私はとにかくそれを言うでしょう:もし私が恩恵を申し立てて、私の恩返しを得ることができないと言われたら、恩恵を申し立てたので、あなたは私を落胆させました。私は恩恵を訴えた後、しばらくしなければならなかったので、私はそれに答えています。 –

+0

こんにちはジョージ、私は個人的にその理由でdownvotedが、私は積み重ねが新しく、自分の賞金を得ることができないことを知らなかった。私は私のdownvoteを取り戻して、あなたのプロフィールを見た後にあなたがスタックのコミットされた、スマートで有用なメンバーであることがわかります:) –

6

まず、あなたのモデルが持っていることを確認する必要がありますすべての既存のレコードにUUID値を追加するにはblank=True, null=Trueで提出されたUUID

次に、southと一緒にschemamigrationコマンドを実行して、結果の移行ファイルを開きます。 そして、このpost

見積もりに示すように、次を使用して移行ファイルを編集します。

あなたが前方に()関数の最後に次のimport UUID

をインポートする必要があります(自己、ORM)前方DEF次の行を追加しますように述べている。意志ループthrouとして

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

既存のインスタンスを表示し、移行の一部としてuuidを追加します。

関連する問題