Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Django ImageField change file name on upload

Tags:

django

Upon saving me model 'Products' I would like the uploaded image to be named the same as the pk for example 22.png or 34.gif I don't want to change the format of the image just the name. How can this be done? example of my model so far below...

image = models.ImageField(         upload_to="profiles",         height_field="image_height",         width_field="image_width",         null=True,         blank=True,         editable=True,         help_text="Profile Picture",         verbose_name="Profile Picture"     )     image_height = models.PositiveIntegerField(null=True, blank=True, editable=False, default="100")     image_width = models.PositiveIntegerField(null=True, blank=True, editable=False, default="100") 
like image 293
jason Avatar asked Feb 28 '13 16:02

jason


2 Answers

You can pass a function into upload_to field:

def f(instance, filename):     ext = filename.split('.')[-1]     if instance.pk:         return '{}.{}'.format(instance.pk, ext)     else:         pass         # do something if pk is not there yet 

My suggestions would be to return a random filename instead of {pk}.{ext}. As a bonus, it will be more secure.

What happens is that Django will call this function to determine where the file should be uploaded to. That means that your function is responsible for returning the whole path of the file including the filename. Below is modified function where you can specify where to upload to and how to use it:

import os from uuid import uuid4  def path_and_rename(path):     def wrapper(instance, filename):         ext = filename.split('.')[-1]         # get filename         if instance.pk:             filename = '{}.{}'.format(instance.pk, ext)         else:             # set filename as random string             filename = '{}.{}'.format(uuid4().hex, ext)         # return the whole path to the file         return os.path.join(path, filename)     return wrapper  FileField(upload_to=path_and_rename('upload/here/'), ...) 
like image 50
miki725 Avatar answered Sep 29 '22 15:09

miki725


Django 1.7 and newer won't make migration with function like this. Based on answer by @miki725 and this ticket, you need to make your function like this:

import os from uuid import uuid4 from django.utils.deconstruct import deconstructible  @deconstructible class UploadToPathAndRename(object):      def __init__(self, path):         self.sub_path = path      def __call__(self, instance, filename):         ext = filename.split('.')[-1]         # get filename         if instance.pk:             filename = '{}.{}'.format(instance.pk, ext)         else:             # set filename as random string             filename = '{}.{}'.format(uuid4().hex, ext)         # return the whole path to the file         return os.path.join(self.sub_path, filename)  FileField(upload_to=UploadToPathAndRename(os.path.join(MEDIA_ROOT, 'upload', 'here'), ...) 
like image 26
bmiljevic Avatar answered Sep 29 '22 14:09

bmiljevic