I've seen a lot of post about this problem without really understanding how to solve it.
I have this model:
class Project(TimeStampedModel):
name = models.TextField(max_length=100, default='no name')
logo = models.ImageField()
I'd like to have my image saved to media root following this template:
<name>/logo/<filename>
At first glance, I would like to do:
logo = models.ImageField(upload_to="{}/logo/".format(name))
But it raises this error: AttributeError: 'TextField' object has no attribute 'model'
Using a callable would be fine, partially though:
def upload_to_project(self, filename):
url = ("%s/%s") % (self.name, filename)
return url
and using:
logo = models.ImageField(upload_to=upload_to_project)
at least I have: <name>/<filename>
But how to pass the argument in this case? I'd like to reuse my function to upload in other subfolders, not only logo
as:
<name>/logo/<filename>
<name>/history/<filename>
<name>/whatever/<filename>
Any idea on what I could do?
It looks like (re-reading your post it's not 100% clear) what you want is a partial application. Good news, it's part of Python's stdlib:
Note that this implementation assumes
instance
has aname
attribute... if the instance attribute you want to use as first part has to be configurable too you can rewrite yourupload_to
as:then use it as
And if you have more than one
FileField
orImageField
in your model and don't want to repeat theattrname
part: