How to give FileField's upload_to parameter a dynamic function?

902 views
Skip to first unread message

Xx Johnsua

unread,
Jan 11, 2017, 5:50:11 AM1/11/17
to Django users
I wrote 3 models:

...
def
generate_mugshot(instance, filename):

    filename, ext = os.path.splitext(filename)
    return "mugshot/%s/%s%s" % (instance.id, uuid4(), ext)

def generate_team_photo(instance, filename):
    filename, ext = os.path.splitext(filename)
    return "team/%s/%s%s" % (instance.id, uuid4(), ext)

def generate_gift_photo(instance, filename):
    filename, ext = os.path.splitext(filename)
    return "gift/%s/%s%s" % (instance.id, uuid4(), ext)


class
User(AbstractUser):

    ...
    mugshot
= models.ImageField(
'头像', upload_to= generate_mugshot, validators=[check_image_extension], null=True, blank=True)

class Team(models.Model):
    ...
    photo
= models.ImageField(
'队标', upload_to= generate_team_photo, validators=[check_image_extension], blank=True, null=True)

class Gift(models.Model):
    ...
    photo = models.ImageField('图片', upload_to= generate_gift_photo, validators=[check_image_extension], null=True, blank=True)

If I want to add a new model, I have to write a new duplicate function "generate_something(instance, filename)", it is not pythonic. So I modify it to following code:

def generate_attachment_by_id(prefix):
    def _return_function(instance, filename):
        filename, ext = os.path.splitext(filename)
        return "%s/%s/%s%s" % (prefix, instance.id, uuid4(), ext)
    return _return_function

...

class User(AbstractUser):
    mugshot = models.ImageField('头像', upload_to=generate_attachment_by_id('mugshot'), validators=[check_image_extension], null=True, blank=True)

class Team(models.Model):
    photo = models.ImageField('队标', upload_to=generate_attachment_by_id('team'), validators=[check_image_extension], blank=True, null=True)

class Gift(models.Model):
    photo = models.ImageField('图片', upload_to=generate_attachment_by_id('gift'), validators=[check_image_extension], null=True, blank=True)

Then I execute makemigrations, an error raised:

ValueError: Could not find function _return_function in app.account.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.


So, how to solve the problem?

Thank you for helping me...

ludovic coues

unread,
Jan 11, 2017, 6:34:55 AM1/11/17
to django...@googlegroups.com
Instead of passing prefix as an argument, you could set it as an
attribute of your models. Something like this:

class User(AbstractUser):
prefix = "mugshot"
mugshot = models.ImageField('AB', upload_to= generate_attachment, ...)

then generate_attachment would be something like that:

def generate_mugshot(instance, filename):
filename, ext = os.path.splitext(filename)
return "%s/%s/%s%s" % (instance.prefix, instance.id, uuid4(), ext)


Should work
> --
> You received this message because you are subscribed to the Google Groups
> "Django users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to django-users...@googlegroups.com.
> To post to this group, send email to django...@googlegroups.com.
> Visit this group at https://groups.google.com/group/django-users.
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/django-users/e11aa79e-a103-4b5e-8420-371599d4a7eb%40googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.



--

Cordialement, Coues Ludovic
+336 148 743 42
Reply all
Reply to author
Forward
0 new messages