Python Django:如何使用基于实例pk的文件名上传文件

Mag*_*gda 5 python django

我有我认为是一个简单的问题.在我的模型中,我有一个models.ImageField,它看起来像这样:

class CMSDocument(BaseItem):
    thumb = models.ImageField(upload_to= './media/',blank=True)
Run Code Online (Sandbox Code Playgroud)

但我想将其上传到'.media/' + self.pk+ '.png'我试图更新模型的save方法中的字段,但这不起作用,因为调用'save'时不知道pk.我也试着为upload_to添加一个自定义函数,如下所示:Django:有什么方法可以改变FileField的"upload_to"属性而不需要魔术?.但这只会让场地空洞.我能做什么?

编辑:我使用Django 1.6

编辑:我使用了一个不太好的post_save信号:

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()
    ...
Run Code Online (Sandbox Code Playgroud)

Mar*_*rcs 3

主键由数据库分配,因此您必须等待模型行保存在数据库上。

首先将数据分为两个模型,缩略图位于子模型上:

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)
Run Code Online (Sandbox Code Playgroud)

如您所见,我使用缩略图的自定义字段而不是 ImageField。

然后创建一个 fields.py 文件,您应该在其中重写 ImageField 继承的 FileField 类的 pre_save 函数:

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
Run Code Online (Sandbox Code Playgroud)

由于 CMSMediaDocument 继承自 CMSDocument 类,因此在调用 pre_save 时,渐进式 PK 已保存在数据库中,因此您可以从model_instance中提取 pk 。

我测试了代码,应该可以正常工作。

测试中使用的admin文件:

from django.contrib import admin

from .models import CMSMediaDocument

admin.site.register(CMSMediaDocument)
Run Code Online (Sandbox Code Playgroud)