简体   繁体   English

我们可以在Django的验证函数中调整ImageField的大小吗?

[英]Can we resize an ImageField from inside a validation function in Django?

Is it legal to modify data from inside a validation function in Django? 从Django中的验证函数内部修改数据是否合法? I need to autoresize images from ImageFields . 我需要从ImageFields自动ImageFields图像。

In the docs it says that these kind of functions should raise ValidationError , but instead I need to actually modify the data ( image in this case). 在文档中它说这些函数应该引发ValidationError ,但我需要实际修改数据(在这种情况下是image )。 I'd like to do it like this because I have to apply this to several models. 我想这样做,因为我必须将它应用于几个模型。 If I could do this, I wouldn't need to change the forms in the admin. 如果我能做到这一点,我就不需要更改管理员中的表单。

def image_field_autoresize(image):
    if image.width > MAX_IMAGE_WIDTH:
        raise ValidationError(u'image width error')
    if image.height > MAX_IMAGE_HEIGHT:
        raise ValidationError(u'image height error')

After a discussion with @karthikr, I can conclude with the following: 在与@karthikr讨论后,我可以得出以下结论:

If you need to change data in a validation process, you can override clean_<fieldname>() from the ModelForm class. 如果需要在验证过程中更改数据,可以从ModelForm类中重写clean_<fieldname>() In your clean() method in ModelForm you shouldn't do that. ModelForm clean()方法中,你不应该那样做。 And if you need to do some image resizing I found that the best place is Model's save() method. 如果你需要做一些图像大小调整,我发现最好的地方是Model的save()方法。

I've solved the problem like this: 我已经解决了这个问题:

I've created a new module named image.py that contains a function that takes as parameter the image's absolute path, implements the resizing logic and modifies the image size. 我创建了一个名为image.py的新模块,其中包含一个函数,该函数将图像的绝对路径作为参数,实现调整大小逻辑并修改图像大小。 In my case, the "resizing logic" reduces the image proportionally if the width is bigger that a given size. 就我而言,如果宽度大于给定大小,“调整大小逻辑”会按比例缩小图像。

from PIL import Image
from django.conf import settings


def autoresize_image(image_path):
    image = Image.open(image_path)
    width = image.size[0]
    if width > settings.IMAGE_MAX_WIDTH:
        height = image.size[1]
        reduce_factor = settings.IMAGE_MAX_WIDTH / float(width)
        reduced_width = int(width * reduce_factor)
        reduced_height = int(height * reduce_factor)
        image = image.resize((reduced_width, reduced_height), Image.ANTIALIAS)
        image.save(image_path)

I call this function from save() method in the Model that contains an ImageField to be resized. 我在模型中的save()方法中调用此函数,该模型包含要调整大小的ImageField Points to keep in mind here: call super() before trying to resize the image or it won't be found as it won't be already saved in your hdd and if the ImageField is not required, check if value is given. 这里要记住的要点:在尝试调整图像大小之前调用super() ,否则将无法找到,因为它不会保存在您的硬盘中,如果不需要ImageField ,请检查是否给出了值。 It looks like: 看起来像:

def save(self, *args, **kwargs):
    super(Startup, self).save(*args, **kwargs)
    if self.logo:
        autoresize_image(self.logo.path)

Thanks to @Jingo as well for his comment. 感谢@Jingo以及他的评论。 It's been very useful :) 它非常有用:)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM