在运行makemigrations时,从django 1.6升级到1.7获取可调用性不是序列化

时间:2015-08-11 23:45:16

标签: python django

我们使用可调用的方式动态生成项目中的upload_to目标,如下所示。

class PKUploader(object):
    def __init__(self, prefix, extension=None):
        self.prefix = prefix
        self.extension = extension

    def __call__(self, instance, filename):
        ext = self.extension or os.path.splitext(filename)[1]
        if not ext.startswith('.'):
            ext = '.' + ext
        if instance.pk is None:
            pk = random.randint(1000, 99999)
        else:
            pk = instance.pk
        pk = str(pk) + str(uuid.uuid4())
        return '{}/{}{}'.format(self.prefix, pk, ext)

在我们的模型中,它像

一样使用
class CoolKids(models.Model):
    image = models.ImageField(upload_to=PKUploader('users_image'))

但是,当我们从django 1.6升级到1.7并运行makemigrations时,我们会收到以下错误。

ValueError: Cannot serialize: <PKUploader object at 0x7ff5f1cf0b90>
There are some values Django cannot serialize into migration files.
For more, see https://docs.djangoproject.com/en/dev/topics/migrations/#migration-serializing

任何人都可以对此有所了解吗?

2 个答案:

答案 0 :(得分:2)

要序列化任意类的实例,您需要实现deconstruct()方法:

class PKUploader(object):
    def __init__(self, prefix, extension=None):
        self.prefix = prefix
        self.extension = extension

    def deconstruct(self):
        kwargs = {'prefix': self.prefix}
        if self.extension is not None:
            kwargs['extension'] = self.extension
        return 'import.path.to.PKUploader', (), kwargs

    def __call__(self, instance, filename):
        ...

通过返回类的导入路径以及位置和关键字初始化参数,Django可以将此信息序列化为重新创建原始实例的有效python代码。

为简化此操作,您可以使用@deconstructible装饰器:

from django.utils.deconstruct import deconstructible

@deconstructible
class PKUploader(object):
    ...

有关详细信息,请参阅documentation

答案 1 :(得分:0)

如果将callable分配给变量,则应该避免此错误。

upload_to = PKUploader('users_image')

class CoolKids(models.Model):
    image = models.ImageField(upload_to=upload_to)