以 lambda 作为默认值且 unique = True 的 Django 字段
Django field with lambda as default value and unique = True
我基本上已经得到了这个模型(其他领域被遗漏了):
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 字段的默认值是预先计算好的,并用于每个新条目,因此它不是每个对象唯一的。我怎样才能让它单独计算每个对象的值?
这应该有效:
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
.
如果要将该列添加到现有的 table,则需要为现有的行提供值。
South 会要求您提供一次性价值,但据我所知只有 datetime
可用。如果是这样,您可以使用 utcnow.strftime
然后 运行 更新 uuid4
作为迁移的一部分。
此外,我建议避免将 lambda 用于字段选项(如默认值)并始终检查自动生成的迁移。
我解决了这个问题。我首先使用 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')
我基本上已经得到了这个模型(其他领域被遗漏了):
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 字段的默认值是预先计算好的,并用于每个新条目,因此它不是每个对象唯一的。我怎样才能让它单独计算每个对象的值?
这应该有效:
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
.
如果要将该列添加到现有的 table,则需要为现有的行提供值。
South 会要求您提供一次性价值,但据我所知只有 datetime
可用。如果是这样,您可以使用 utcnow.strftime
然后 运行 更新 uuid4
作为迁移的一部分。
此外,我建议避免将 lambda 用于字段选项(如默认值)并始终检查自动生成的迁移。
我解决了这个问题。我首先使用 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')