Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
463 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 Answer

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.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

2.1m questions

2.1m answers

60 comments

56.8k users

...