Django 在某些情况下重写模型的 save 方法?

181 投票
7 回答
283622 浏览
提问于 2025-04-16 07:33

在保存Model实例之前,我需要调整一下image的大小。我该怎么判断是新图片被添加了,还是只是更新了描述呢?这样我就可以在每次保存模型的时候跳过调整大小的步骤。

class Model(model.Model):
    image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()


    def save(self, *args, **kwargs):
        if self.image:
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

我只想在加载了新图片或者更新了图片的时候调整大小,而不是在更新描述的时候。

7 个回答

10

你可以提供额外的参数来确认一个新的图片已经上传。
就像这样:

def save(self, new_image=False, *args, **kwargs):
    if new_image:
        small=rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)
    super(Model, self).save(*args, **kwargs)

或者传递请求变量

def save(self, request=False, *args, **kwargs):
    if request and request.FILES.get('image',False):
        small=rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)
    super(Model, self).save(*args, **kwargs)

我觉得这些在简单调用时不会影响你的保存功能。

你可以把这个放在你的 admin.py 文件里,这样它也能在管理网站上工作(针对上面第二个解决方案):

class ModelAdmin(admin.ModelAdmin):

    ....
    def save_model(self, request, obj, form, change): 
        instance = form.save(commit=False)
        instance.save(request=request)
        return instance
27

检查模型的主键字段。如果它是空的,那就是一个新对象。

class Model(model.Model):
    image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()


    def save(self, *args, **kwargs):
        if 'form' in kwargs:
            form=kwargs['form']
        else:
            form=None

        if self.pk is None and form is not None and 'image' in form.changed_data:
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

补充说明:我添加了一个检查,看看表单中是否有'图片'的变化。这是基于你在管理后台更新图片的前提下的。你还需要按照下面的说明,重写默认的保存模型方法。

class ModelAdmin(admin.ModelAdmin):
    def save_model(self, request, obj, form, change):
        obj.save(form=form)
171

一些想法:

class Model(model.Model):
    _image=models.ImageField(upload_to='folder')
    thumb=models.ImageField(upload_to='folder')
    description=models.CharField()

    def set_image(self, val):
        self._image = val
        self._image_changed = True

        # Or put whole logic in here
        small = rescale_image(self.image,width=100,height=100)
        self.image_small=SimpleUploadedFile(name,small_pic)

    def get_image(self):
        return self._image

    image = property(get_image, set_image)

    # this is not needed if small_image is created at set_image
    def save(self, *args, **kwargs):
        if getattr(self, '_image_changed', True):
            small=rescale_image(self.image,width=100,height=100)
            self.image_small=SimpleUploadedFile(name,small_pic)
        super(Model, self).save(*args, **kwargs)

不太确定它是否能和所有伪自动的Django工具配合得很好(比如:ModelForm,contrib.admin等等)。

撰写回答