ValueError: Please move the function into the main module body to use migrations

ValueError: Please move the function into the main module body to use migrations

我正在尝试修复的错误

ValueError: Could not find function func in posts.models. Please note that due to Python 2 limitations, you cannot serialize unbound method functions (e.g. a method declared and used in the same class body). Please move the function into the main module body to use migrations. For more information, see https: //docs.djangoproject.com/en/1.11/topics/migrations/#serializing-values

简介: 我正在使用 Django==1.11.20 和 Ubuntu 18.04。我的 python 版本是 3.6.7 当我在我的 Django 项目中做

(venv)some_path$ python --version
Python 3.6.7

然而,当我在我的 Ubuntu 终端上做同样的事情时,我得到

marco@VB:~$ python --version
Python 2.7.15rc1

marco@VB:~$ python3 --version
Python 3.6.7

关于我的项目:我有以下型号

def upload_name (user_fld='user', prefix=None):
    def func(instance, fname):
        #return os.path.join(prefix, fname) if prefix else fname
        attrs = user_fld.split('.')
        user = instance
        print ("Getattr %s %s" % (attrs, user))
        try:
            for attr in attrs:
                user = getattr(user, attr)
        except:
            username = 'anon'
        else:
            username = user.username

        print ("Upload name** %s, %s" % (instance.pk, username))
        # Extract the raw fname
        fparts = fname.split('.')
        base = fparts[0]
        try:
            atoms = base.split("_")
            ts = datetime.strptime('_'.join(atoms[-7:]), "%Y_%m_%d_%H_%M_%S_%f")
            ousername = atoms[-8]
            base = '_'.join(atoms[:-8])
        except:
            # Any exception in handling this means it wasn't already equipped with our
            # extension so add it on
            pass

        ts = datetime.now()
        fname = '%s_%s_%s%s' % (base, username, ts.strftime("%Y_%m_%d_%H_%M_%S_%f"),
                                ('.%s' % '.'.join(fparts[1:])) if len(fparts) > 1 else '')
        return os.path.join(prefix, fname) if prefix else fname

    return func

class Post(models.Model):
    user = models.ForeignKey(User, related_name='posts')
    title = models.CharField(max_length=250, unique=True)
    slug = models.SlugField(allow_unicode=True, unique=True, max_length=500)
    post_image = models.ImageField(null=True, blank=True, upload_to=upload_name())

class Prep (models.Model): #(Images)
    post = models.ForeignKey(Post, on_delete=models.CASCADE, related_name='post_prep')
    image = models.ImageField(upload_to=upload_name('post.user', 'images/'), blank=True, null=True, default='')
    image_title = models.CharField(max_length=100, default='')

试图找出如何添加 deconstruct() 方法

https://docs.djangoproject.com/en/1.11/topics/migrations/#adding-a-deconstruct-method

Trying @RaydelMiranda solution

def upload_name_factory(instance, fname, user_fld='user', prefix=None):
    attrs = user_fld.split('.')
    user = instance
    print("Getattr %s %s" % (attrs, user))
    try:
        for attr in attrs:
            user = getattr(user, attr)
    except:
        username = 'anon'
    else:
        username = user.username

    print("Upload name** %s, %s" % (instance.pk, username))
    # Extract the raw fname
    fparts = fname.split('.')
    base = fparts[0]
    try:
        atoms = base.split("_")
        ts = datetime.strptime('_'.join(atoms[-7:]), "%Y_%m_%d_%H_%M_%S_%f")
        ousername = atoms[-8]
        base = '_'.join(atoms[:-8])
    except:
        # Any exception in handling this means it wasn't already equipped with our
        # extension so add it on
        pass

    ts = datetime.now()
    fname = '%s_%s_%s%s' % (base, username, ts.strftime("%Y_%m_%d_%H_%M_%S_%f"),
                            ('.%s' % '.'.join(fparts[1:])) if len(fparts) > 1 else '')
    return os.path.join(prefix, fname) if prefix else fname


upload_name = partial(upload_name_factory, user_fld='user', prefix=None)

我明白你想做什么,你希望能够重用传递给 upload_to 的函数,能够自定义 user_fldprefix 参数。

所以,您已经知道必须将函数移至主模块主体。如何做到这一点并保持您的可重用性想法?

部分函数。

from django.db import models
from functools import partial

def upload_name_factory(instance, filename, user_fld='user', prefix=None):
    attrs = user_fld.split('.')
    user = instance
    # ...

upload_name = partial(upload_name_factory, user_fld='user', prefix="/some/prefix/")

class Foo(models.Model):
    f = models.FileField(upload_to=upload_name)  

阅读更多关于偏音的内容 here