Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python Django: How to upload a file with a filename based on instance pk

Tags:

python

django

I have what I considered to be a simple question. Within my model I have a models.ImageField which looks like that:

class CMSDocument(BaseItem):
    thumb = models.ImageField(upload_to= './media/',blank=True)

But I would like to upload it to '.media/' + self.pk+ '.png' I tried to update the field within the save method of the model, but this does not work, as the pk is not known when 'save' is called. I also tried to add a custom function for upload_to as suggested here: Django: Any way to change "upload_to" property of FileField without resorting to magic? . But this just leaves the field empty. What can I do?

EDIT: I use Django 1.6

EDIT: I used a post_save signal which is not very nice:

def video_embed_post_save(sender, instance=False, **kwargs):    
    document = DocumentEmbedType.objects.get(pk=instance.pk)    
    new_thumb = "media/%s.png" % (document.pk,)
    if not document.thumb == new_thumb:
        document.thumb = new_thumb
        document.save()
    ...
like image 593
Magda Avatar asked Oct 19 '22 21:10

Magda


1 Answers

The primary key is assigned by the database so you have to wait until your model row is saved on the db.

Firstly divide your data in two models, with the thumbnail on the child model:

from django.db import models

from .fields import CMSImageField


class CMSDocument(models.Model):
    title = models.CharField(max_length=50)


class CMSMediaDocument(CMSDocument):
    thumb = CMSImageField(upload_to='./media/', blank=True)

As you see I'm using a custom field for the thumbnail instead of the ImageField.

So then create a fields.py file where you should override the pre_save function of the FileField class inherited by ImageField:

from django.db import models


class CMSImageField(models.ImageField):
    def pre_save(self, model_instance, add):

        file = super(models.FileField, self).pre_save(model_instance, add)

        if file and not file._committed:
            # Commit the file to storage prior to saving the model
            file.save('%s.png' % model_instance.pk, file, save=False)
        return file

Because CMSMediaDocument is inheriting from the CMSDocument class, at the moment that pre_save is called, the progressive PK is already saved in the database so you can extract the pk from model_instance.

I tested the code and should work fine.

The admin file used in the test:

from django.contrib import admin

from .models import CMSMediaDocument

admin.site.register(CMSMediaDocument)
like image 127
Marcs Avatar answered Nov 03 '22 07:11

Marcs