优化Django模型保存方法以访问上传文件路径

4 投票
2 回答
767 浏览
提问于 2025-04-19 00:08

在我的Django应用程序模型中,我需要在save()方法里访问一个ImageField,以提取一些GPS信息,并在保存整个模型实例之前填充其他MyModel字段。

def save(self, force_insert=False, force_update=False, using=None, update_fields=None):
    if self.image:
        # Todo: remove the double call of super(Photo, self).save() method by accessing the file before it will save
        super(Photo, self).save(force_insert, force_update, using, update_fields)
        image_file = gpsimage.open(self.image.path)  #gpsimage.open needs a file path that I can have it only after I call super(Photo, self).save(....)
        ...
        ...
        ...
        # Final save call
        super(Photo, self).save(force_insert, force_update, using, update_fields)

有没有办法访问一个临时文件(图片)的路径,从中提取信息,然后如果所有字段都有效,就保存整个模型?还有其他优雅的解决方案吗?

我现在的应用是一个REST和管理应用,所以我希望把这个逻辑添加到一个中心模型中。

2 个回答

0

我之前也遇到过同样的问题,我的解决办法是保存两次。下面是我的代码:

 26     def save(self, *args, **kwargs):
 27         super(GeoFile, self).save(*args, **kwargs)
 28         self.filetype = self.possible_type()
 29         if self.filetype == 'SHPZ':
 30             self.fileinfo = self.shpz_info()
 31             if 'srid' in self.fileinfo and not self.fileinfo['srid'] is None:
 32                 self.srid = self.fileinfo['srid']
 41         super(GeoFile, self).save()
2

你可以通过自定义保存方法来获取文件路径,方法是使用 self.myimg.name,其中 myimg 是你定义的字段名。

from django.db import models
import uuid
import os

def img_file_path(instance, filename):
    ''' Creates a filepath and name for an image file. '''
    ext = filename.split('.')[-1]
    filename = "%s.%s" % (uuid.uuid4(), ext)
    today = datetime.date.today()
    return os.path.join('imgs', '%s/%s/%s' % (today.year, today.month, today.day), filename)

class MyModel(models.Model):
    myimg = models.ImageField(upload_to = img_file_path)

    def save(self, *args, **kwargs):
        path_of_file = self.myimg.name

        # edit path_of_file, or whatever
        self.myimg.name = path_of_file.upper()

        super(MyModel, self).save()

如果你查看一下 源代码,你会发现文件名是在 __init__() 方法中确定的,所以一旦对象被创建,你就可以访问这个文件名了(在保存和提交之前)。

撰写回答