Поле Django с лямбдой в качестве значения по умолчанию и уникальным = 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 предварительно рассчитано и используется для каждой новой записи, и поэтому оно не уникально для каждого объекта. Как я могу получить его для расчета стоимости для каждого объекта в отдельности?

2 ответа

Решение

Я исправил это. Сначала я создал поля с null=True и unique=False, затем я программно предоставил значения для полей uuid, а затем изменил поля, чтобы сделать их уникальными = 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')

Это должно работать:

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 как часть миграции.

Кроме того, я бы посоветовал избегать использования лямбда-выражений для параметров полей, таких как default, и всегда проверять автоматически созданные миграции.

Другие вопросы по тегам