2015-10-20 68 views
2

我有基本上這種模式(其他領域排除在外):與lambda作爲默認值和獨特的Django字段=真

class GiftBase(models.Model): 
    """ 
     A base class for describing gift type items. 

    """ 
    uuid = models.CharField(max_length=32, default=lambda: uuid.uuid4().hex, unique=True) 

當我做

./manage.py schemamigration facebookapp --auto 
./manage.py migrate facebookapp 

我得到這個輸出

Running migrations for facebookapp: 
- Migrating forwards to 0053_auto__add_field_giftbase_uuid__add_field_purchase_uuid. 
> facebookapp:0053_auto__add_field_giftbase_uuid__add_field_purchase_uuid 
FATAL ERROR - The following SQL query failed: ALTER TABLE "facebookapp_giftbase" ADD COLUMN "uuid" varchar(32) NOT NULL UNIQUE DEFAULT '8de722a747974db3aab4c1fdaa618f16'; 
The error was: could not create unique index "facebookapp_giftbase_uuid_key" 
DETAIL: Key (uuid)=(8de722a747974db3aab4c1fdaa618f16) is duplicated. 

從這裏我意識到,uuid字段的默認值是預先計算好的並用於每個新條目,因此它不是唯一的ea ch對象。我怎樣才能得到它分別計算每個對象的值?

+0

能否請您分享遷移? –

+0

正如你所看到的,默認值在你的遷移中被硬編碼。 –

回答

0

我弄明白了。我首先創建了null = True和unique = False的字段,然後以編程方式爲uuid字段提供值,然後更改字段以使其unique = True,並在其上使用create_unique。

下面的代碼:

# -*- coding: utf-8 -*- 
from south.utils import datetime_utils as datetime 
from south.db import db 
from south.v2 import SchemaMigration 
from django.db import models 

import uuid 


class Migration(SchemaMigration): 

    def forwards(self, orm): 
     # Adding field 'Company.uuid' 
     db.add_column(u'facebookapp_company', 'uuid', 
         self.gf('django.db.models.fields.CharField')(max_length=32, null=True), 
         keep_default=False) 

     # Adding field 'GiftBase.uuid' 
     db.add_column(u'facebookapp_giftbase', 'uuid', 
         self.gf('django.db.models.fields.CharField')(max_length=32, null=True), 
         keep_default=False) 

     # Adding field 'Purchase.uuid' 
     db.add_column(u'facebookapp_purchase', 'uuid', 
         self.gf('django.db.models.fields.CharField')(max_length=32, null=True), 
         keep_default=False) 

     for model in (orm.Company, orm.GiftBase, orm.Purchase): 
      for obj in model.objects.all(): 
       obj.uuid = uuid.uuid4().hex 
       obj.save() 

     db.alter_column(u'facebookapp_company', 'uuid', 
       self.gf('django.db.models.fields.CharField')(max_length=32, unique=True, null=False)) 
     db.create_unique(u'facebookapp_company', ['uuid']) 

     db.alter_column(u'facebookapp_giftbase', 'uuid', 
       self.gf('django.db.models.fields.CharField')(max_length=32, unique=True, null=False)) 
     db.create_unique(u'facebookapp_giftbase', ['uuid']) 

     db.alter_column(u'facebookapp_purchase', 'uuid', 
       self.gf('django.db.models.fields.CharField')(max_length=32, unique=True, null=False)) 
     db.create_unique(u'facebookapp_purchase', ['uuid']) 


    def backwards(self, orm): 
     # Deleting field 'Company.uuid' 
     db.delete_column(u'facebookapp_company', 'uuid') 

     # Deleting field 'GiftBase.uuid' 
     db.delete_column(u'facebookapp_giftbase', 'uuid') 

     # Deleting field 'Purchase.uuid' 
     db.delete_column(u'facebookapp_purchase', 'uuid') 
2

這應該工作:

from uuid import uuid4 

from django.db.models import Model, CharField 


def get_default_uuid(): 
    return uuid4().hex 


class GiftBase(Model): 
    """ 
    A base class for describing gift type items. 
    """ 
    uuid = CharField(max_length=32, default=get_default_uuid, unique=True) 

不要忘記檢查自動生成的遷移。如果仍然存在硬編碼值,請嘗試將get_default_uuid直接放入遷移文件,然後編輯default

如果要將該列添加到已存在的表中,則需要爲現有行提供值。

南方會問你一次性的價值,但據我所知只有datetime可用。如果是這樣,您可以使用utcnow.strftime,然後運行更新uuid4作爲遷移的一部分。

此外,我建議避免使用lambda作爲默認字段選項,並始終檢查自動生成的遷移。

+0

我試過了,得到了同樣的結果。 –

+0

沒有注意到你正在使用'south'。更新了我的答案。 –