pythondjangodjango-file-uploadpim

Django ImageField/FileField save uploaded file using model's pk


I'm converting a legacy site (originally written in rails) and by default the images were saved using the format {{pk}}.{{extension}} and that file was always overwritten if a new file is uploaded. I'd like to continue that format with this django version.

I originally thought extending FileSystemStorage would be te way to go, but I don't know of a way to pass the current model object to it. Anyone have a suggestion on a "django way" to accomplish this?

If I need to write my own class that extends ImageField to manage this, then so be it. :) Just wondering if there was something simple I'm missing.

[edit] WHAT I DID, BASED ON ANSWER FROM surfeurx and DrTyrsa:

temp_image = None

def image_path(self, uploaded_file_name):
    prefix = 'designs/'
    extension = os.path.splitext(uploaded_file_name)[-1]
    if self.pk != None:
        return prefix + str(self.pk) + extension
    else:
        tmp_name = str(uuid.uuid4())
        self.temp_image = prefix + tmp_name + extension
        return self.temp_image

image_upload = models.ImageField(upload_to=image_path, null=True, blank=True) 

def save(self):
    self.updated_at = datetime.now()

    is_new = self.pk == None
    super(Design, self).save()

    if is_new:
        if self.temp_image != None:
            os.rename(MEDIA_ROOT + self.temp_image, MEDIA_ROOT + self.image_path(self.temp_image))
            self.temp_image = None

The real problem I'm having now is that I want it to overwrite the image. This will provide the right file name, but it looks like I'm going to have to extend ImageField to get it to overwrite. Found this little guy: http://djangosnippets.org/snippets/636/


Solution

  • You can use upload_to like:

    def image_path(instance, filename):
        return instance.id + os.path.splitext(filename)[1]
    
    class Brand(models.Model):
        ...
        logo = models.ImageField(upload_to=image_path, null=True, blank=True)