Ok, it cannot be a lambda, since lambdas are not serializable for some reason but here's the easy answer.
def pic_loc(instance, filename):
"""
:param instance: Product Instance
:param filename: name of image being uploaded
:return: image location for the upload
"""
return '/'.join([str(instance.pk), str(instance.slug), filename])
Class Product(models.Model):
image = models.ImageField(upload_to=pic_loc)
slug = models.SlugField()
user = models.ForeignKey(User, related_name="products")
Then to find say pk = 1 with:
slug = 'new-thing' would be //myexample.com/MEDIA_ROOT/1/new-thing/mything.png
<img src="{{ obj.image.url }}">
This is assuming you have MEDIA_ROOT set since uploads go to media and media url. Serve up like you did static files if in production, name it after MEDIA_URL.
upload_to passes both the object instance and the filename to a your function, from there you can manipulate it.
To change the actual filename you need to do some extra work in the save() method.
from django.core.files import File
class Product(models.Model):
label = CharField(max_length=255)
...
def save(self, **kwargs):
# here we use os.rename then change the name of the file
# add condition to do this, I suggest requerying the model
# and checking if label is different
if self.pk: # Need this to mitigate error using self.pk
if Product.objects.get(pk=self.pk).label != self.label:
path = self.image.path
rename = '/'.join(path.split('/')[:-1]) + '/' + self.label
os.rename(path, rename)
file = File(open(rename))
self.image.save(self.label, file)
return super(Product, self).save(**kwargs)
If the file extension is important which it very well may be, either add it to label when creating label or we take the old file extension as part of the string:
filename, file_extention = os.splitext(path)
rename += file_extension # before renaming and add to label too
os.rename(path, rename)
self.image.save(self.label + file_extension, file)
I would actually suggest writing a rename function as part of your app_label.utils
To check if the file exists is simply
if os.path.isfile(rename):
# you can also do this before renaming,
# maybe raise an error if the file already exists
label
ed filename to the original file? – Anthropomorphosisos.rename
call in the model's save() method with a large third-party dependency counts as being an easier solution. (That being said, django-smartfields still looks very promising if your goal is to replace code with dependency declarations.) – Anthropomorphosis