【问题标题】:Upgrading from django 1.6 to 1.7 getting callable is not serialize when running makemigrations运行 makemigrations 时,从 django 1.6 升级到 1.7 变得可调用不是序列化
【发布时间】:2015-11-04 09:19:58
【问题描述】:

我们使用可调用对象在项目中动态生成 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

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

【问题讨论】:

    标签: python django


    【解决方案1】:

    要序列化任意类的实例,需要实现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

    【讨论】:

      【解决方案2】:

      如果将可调用对象分配给变量,则应避免此错误。

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

      【讨论】:

      • 这有什么关系?
      • 当字段定义中有PKUploader('users_image')时,它是一个匿名函数(即它没有绑定一个名字),所以它不能被序列化。将结果分配给变量允许对其进行序列化。
      • 这似乎不是问题:S
      猜你喜欢
      • 1970-01-01
      • 2015-05-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-09-21
      • 2015-02-06
      • 2015-02-23
      相关资源
      最近更新 更多