2015-10-20 46 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'。更新了我的答案。 –