【问题标题】:How can I open a image from an ImageField before validating and saving a form?如何在验证和保存表单之前从 ImageField 打开图像?
【发布时间】:2012-09-20 14:40:40
【问题描述】:

我想根据ImageField 的值获取CharField 的值。我的表单和视图定义为:

#Form
class GpsImForm(forms.Form):
    image = forms.ImageField(required=True)
    gps_data = forms.CharField(required=True)

#View
def gpsim_gen_view(request):
    if request.method == 'POST':
        form = GpsImForm(request.POST, request.FILES)
        if 'image' in request.FILES:
            im = request.FILES['image']
            i = Image.open(im)
            ... # functions to extract exif data from i
            request.POST.update({ 'gps_data': ...}) # set gps_data based on exif data from i
        if form.is_valid():
            obj = form.save()
            return ... #returns the gpsim
    else:
        form = GpsImForm()
    return direct_to_template(request, 'gpsim_generate.html', {'form': form,})

gps_data 已更新,但是,一旦我使用 Image.open(),就会收到以下错误消息:

上传一张有效的图片。您上传的文件不是图片或损坏的图片。

如果我评论有关i 的行并将gps_data 修改为任何内容,则表单(带有图像)将被保存而没有任何错误...

# i = Image.open(im)
# ...
# functions to extract exif data from i
request.POST.update({ 'gps_data': 'some text'}) # set gps_data to 'test'

【问题讨论】:

  • 你尝试过什么类型的图片?在不支持 jpeg 的情况下安装 PIL 是一个常见问题,在这种情况下,您需要卸载 PIL,安装 libjpeg,然后重新安装 PIL。
  • 真的,问题不在于 libjpeg。正如问题最后所说,当我不使用 Image.open() 时,表单(带有图像)被保存而没有任何错误。无论如何谢谢:-)
  • 您的问题听起来和这个类似,所以我正在检查您是否尝试过其他文件类型:stackoverflow.com/questions/1398701/…

标签: python django django-forms django-views python-imaging-library


【解决方案1】:

我终于找到了一个更干净的解决方案: 我从我的模型中删除了“required=True”,并定义了一个 clean() 方法,它在我的表单模型中完成这项工作:

#Form
class GpsImForm(forms.Form):
    image = forms.ImageField(required=True)
    gps_data = forms.CharField()

    def clean(self):
        super(forms.Form, self)).clean()
        if not self.cleaned_data['gps_data']:  # the user can provide the gps_data manually
            if self.cleaned_data['image']:     # if he provided no gps_data but an image
                i = Image.open(self.cleaned_data['image'])
                ... # functions to extract exif data from i
            else:
                msg = _("You have to provide an image or a gps_data.")
                self._errors['gps_data'] = self.error_class([msg]) 
        return self.cleaned_data


#View
def gpsim_gen_view(request):
    if request.method == 'POST':
        form = GpsImForm(request.POST, request.FILES)
        if form.is_valid():
            obj = form.save()
            return ... #returns the gpsim
    else:
        form = GpsImForm()
    return direct_to_template(request, 'gpsim_generate.html', {'form': form,})

【讨论】:

    【解决方案2】:

    首先,确保你的表单有 enctype 标签

    <form enctype="multipart/form-data" ... >    
    

    尝试将img(所有块)写入磁盘:

    import Image
    from random import choice
    from django.conf import settings
    
    random_file_name = getattr(settings, 'FILE_UPLOAD_TEMP_DIR', '/tmp')
    random_file_name +=  '/' + ''.join([choice('abcdefg') for i in range(12)]) + '.jpg'
    
    destination = open(random_file_name, 'wb+')
    for chunk in request.FILES['image'].chunks():
        destination.write(chunk)
    destination.close()
    

    然后,您可以从磁盘打开它:

    image = Image.open(random_file_name)
    if image.mode != "RGB":
        image = image.convert("RGB")
    
    ...
    

    此网址可能对您有所帮助:

    https://docs.djangoproject.com/en/dev/topics/http/file-uploads/

    【讨论】:

    • 是的,我有 enctype 标签。您的解决方案很可能会起作用,但必须做所有这些事情很无聊:(。我提供的解决方案可能是实现我想要的更清洁的方法去做。谢谢!
    猜你喜欢
    • 2012-06-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-11-26
    相关资源
    最近更新 更多