ValueError: Please move the function into main module body to use migrations
Posted
技术标签:
【中文标题】ValueError: Please move the function into main module body to use migrations【英文标题】:ValueError: Please move the function into the main module body to use migrations 【发布时间】:2019-09-29 05:30:41 【问题描述】:我正在尝试修复的错误
ValueError:在posts.models 中找不到函数func。 请注意,由于 Python 2 的限制,您不能序列化未绑定的方法函数(例如,在同一类主体中声明和使用的方法)。请将该功能移动到主模块主体中以使用迁移。 有关详细信息,请参阅 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
尝试@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)
【问题讨论】:
问题是 Django 使用 reference,因此你不能使用这样的包装方法。 @PatrickArtner 我没有混合它们。 Ubuntu 18.04 默认使用 Python 2.7。我的项目正在使用 3.6 我不认为这应该是一个问题,因为我的项目显示 3.6。我不知道为什么 2.7 会参与进来 @WillemVanOnsem 有什么我可以解决的问题。我曾经用 image_name_admin_2019_04_28_02_08_32_204448.jpg 之类的名称保存我的图像 @PatrickArtner 我在上面添加了一张图片。我相信它使用的是3.6。加上pycharm终端也说3.6 【参考方案1】:我明白你想要做什么,你希望能够重用传递给 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)
阅读有关部分的更多信息here。
【讨论】:
我已经在顶部尝试了您的解决方案。我做对了吗 不,只要把func的主体变成upload_name_factory的主体,用这个解决方案你就不需要内部函数了 我已经编辑了答案以便给你一个更好的主意 我已经编辑了我的代码,也见上面的问题。现在我收到以下错误TypeError: upload_name_factory() missing 2 required positional arguments: 'instance' and 'fname'
what about: def upload_name(instance, filename): return upload_name_factory(instance, filename, user_fld='user', prefix="/some/prefix/")以上是关于ValueError: Please move the function into main module body to use migrations的主要内容,如果未能解决你的问题,请参考以下文章