Python Django: how to upload file with file name based on pk instance

I have what I thought was a simple question. In my model, I have models.ImageField that looks like this:

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 updating the field in the save method of the model, but this will not work, since pk is not known when save is called. I also tried adding a custom function for upload_to, as suggested here: Django: any way to change the "upload_to" FileField property without resorting to magic? . But that just leaves the field blank. What can I do?

EDIT: I am using Django 1.6

EDIT: I used the post_save signal, which is not very pleasant:

 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() ... 
+5
source share
1 answer

The primary key is assigned by the database, so you need to wait until your model string is saved to db.

First, split the data in two models with a 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 can see, I use a custom thumbnail field instead of ImageField.

So, create a fields.py file where you must 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 

Since CMSMediaDocument is inherited from the CMSDocument class, the moment the pre_save is called, the progressive PK is already stored in the database, so you can extract pk from model_instance.

I tested the code and should work fine.

Administrator file used in the test:

 from django.contrib import admin from .models import CMSMediaDocument admin.site.register(CMSMediaDocument) 
+3
source

Source: https://habr.com/ru/post/1207950/


All Articles