ValueError: Пожалуйста, переместите функцию в тело основного модуля, чтобы использовать миграции - PullRequest
0 голосов
/ 11 мая 2019

Ошибка, которую я пытаюсь исправить

ValueError : Не удалось найти функцию func в posts.models.Обратите внимание, что из-за ограничений Python 2 вы не можете сериализовать функции несвязанного метода (например, метод, объявленный и используемый в том же теле класса).Пожалуйста, переместите функцию в основной модуль, чтобы использовать миграции.Для получения дополнительной информации см. Https: //docs.djangoproject.com/en/1.11/topics/migrations/#serializing-values

Intro: Я использую 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

enter image description here

Попытка решения @RaydelMiranda

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)

1 Ответ

1 голос
/ 14 мая 2019

Я вижу, что вы хотите сделать, вы хотите иметь возможность повторно использовать передаваемую вами функцию upload_to, имея возможность настраивать параметры user_fld и prefix.

Итак, вы уже знаете, что должны переместить функцию в основной корпус модуля. Как это сделать и сохранить идею повторного использования?

Частичные функции.

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)  

Подробнее о частичках здесь .

...