Well, it can't be lambda, because lambdas are not serialized 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 pk = 1 s:
slug = 'new-thing' will be //myexample.com/MEDIA_ROOT/1/new-thing/mything.png
<img src="{{ obj.image.url }}">
It is assumed that you have MEDIA_ROOT installed, as the download is downloaded to the media and media address. Serve how you made static files, if during production, name it after MEDIA_URL.
upload_to passes the instance of the object and the file name to your function, from there you can manipulate it.
To change the actual file name, you need to do additional 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 can be very good, add it to the label when creating the shortcut or we will take the old file extension as part of the line:
filename, file_extention = os.splitext(path) rename += file_extension
I would suggest writing a rename function as part of your app_label.utils
To check if a file exists, simply
if os.path.isfile(rename):