Reputation: 1191
The error that I am trying to Fix
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
Intro: I am using Django==1.11.20 and Ubuntu 18.04. My python version is 3.6.7 When I do in my Django project in the
(venv)some_path$ python --version
Python 3.6.7
However when I do the same in my Ubuntu terminal I get
marco@VB:~$ python --version
Python 2.7.15rc1
marco@VB:~$ python3 --version
Python 3.6.7
About my project: I have the below models
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='')
Trying to figure out how to add the deconstruct() method
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)
Upvotes: 0
Views: 149
Reputation: 14360
I see what you want to do, you want to be able to reuse the function you pass to upload_to
being able to customize the user_fld
and the prefix
params.
So, you already know you have to move the function to the main module body. How to do that and keep your idea of reusability?
Partial functions.
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)
Read more about partials here.
Upvotes: 1