Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
487 views
in Technique[技术] by (71.8m points)

python - Upgrading from django 1.6 to 1.7 getting callable is not serialize when running makemigrations

We dynamically generate the upload_to destination in our project using a callable, like below.

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)

And in our models it's used like

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

However, when we run upgraded from django 1.6 to 1.7 and run makemigrations we get the following error.

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

Can any one shed some light into this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

To serialize an instance of an arbitrary class, you need to implement a deconstruct() method:

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):
        ...

By returning the import path to the class, and the positional and keyword initialisation arguments, Django can serialize this information to valid python code that recreates the original instance.

To simplify this, you can use the @deconstructible decorator:

from django.utils.deconstruct import deconstructible

@deconstructible
class PKUploader(object):
    ...

See the documentation for full details.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...