【问题标题】:Django FileField not validating with a SimpleUploadedFile ObjectDjango FileField 未使用 SimpleUploadedFile 对象进行验证
【发布时间】:2012-05-14 10:33:51
【问题描述】:

我正在通过 ajax 上传文件,然后创建一个 SimpleUploadFile 对象并将其传递给替换 request.FILES——这不会传递 form.is_valid()。我在下面记录了 SimpleUploadedFile 字典和 request.FILES 替换;如您所见,可以创建 SimpleUploadedFile 对象:

SimpleUploadedFile [This does not work.]:
{'book_pics': <SimpleUploadedFile: movies.jpg (text/plain)>} # Yielded by printing uploaded_file

当我不使用 ajax 并简单地使用表单提交文件时[出于好奇我这样做了],这里是 upload_file 的样子:

request.FILE generated InMemoryUploadedFile [This works.]:
<MultiValueDict: {u'book_pics': [<InMemoryUploadedFile: movies.jpg (image/jpeg)>]}>

知道如何让 SimpleUploadedFile 进行验证吗?

def add_book(request):
    if request.method == 'POST':
        # Grabbing the file uploaded via ajax earlier.
        fh = File(file(settings.MEDIA_ROOT + request.POST['book_pics']))
        uploaded_file = {'book_pics':SimpleUploadedFile(fh.name, fh.read())}
        form = BookForm(data=request.POST, files=uploaded_file)
        if form.is_valid():
            print >> sys.stderr, "Form is valid."
            form.save()
            return render(request, 'generic_message.html', {'message': 'Succesfully added book.'})
        else:
           ...
    else:
        ...

根据这些文档,SimpleUploadedFile 应该可以工作:https://docs.djangoproject.com/en/dev/ref/forms/api/

编辑:

当我打印 f.clean(my_file) 时,我收到以下错误,上下文如下。无论是否在 my_file 中设置文件类型都会发生这种情况:

fh = File(file(settings.MEDIA_ROOT + request.POST['book_pics']))
my_file = UploadedFile(fh.name, fh.read(), 'image/jpeg')
f = forms.FileField()
print >> sys.stderr, f.clean(my_file)
# f.clean(my_file) Returns an error: 

DjangoUnicodeDecodeError: 'utf8' codec can't decode byte 0x92 in position 18: invalid 
start byte. You passed in '<UploadedFile: 
X\x06\x18\x92HI\xde\xf0\x00\xdd\x7f\n\x8e\xf9\x8f\xe5\x00\x92IGa\xaa\xce\xfe_\xa4\x04\xe
3\xca\x1a,\x97\x99\xd0\xda\x02\xe3e\xa8\xbb=\x99\xe0\x00\x0b\xfd?
Q\x00\x02\x80\x00*\xe6\xf7\xb0\xd6\xfb@\x06\xd2\x1f7\xfd\xaf\x00\x04Iw}\x8b\x08\xbcxB\xc
bj\x1e\xa3\x7f1\xf9\xc3\xc3\xef"r\xfb\xcc"T\xa2\x01r\xe7X\xb0\xa3\xc4r\xea\xdf\x9c\x00>\
x96K\x0b\xee\x07\xd26<\xa0\r\xb8\xf2?\xa4\\\x94\xf96\xe43\x1f\xc5\xfa\x1f\xd8@ 
t\xe9\xea\x7f8\x00p?S\xf9\xc0\x01\xc6\xaa\x1b\x06a\xca-
\x1f\xba\x88\xa6\xedn,|\'\xa2\xd8t\xb0\x862\\\xb0\xfa\x17\x16<\xf7\x80\xc1\xce\xc3\xcc\x
fe\x91Xp\x02\xc5\x92\x96\xb3\xa9\x8bo\xac8\x0eQ\xa1\xf3\x80\x07(\xf8GR\xf1x\xf0\x80($\xa
8\x02K76\xda4\x03h\x07\x9f\xed\x00\x07\x1f\x12F\xc7\xfbC\xc3\x90\x16\t\xca\xeeu;\xf4\x8a
\x92\x9f#\xa4\x12Ar\xf7\x80A\xcaId\xdfR\xc7\xae\xb0\xf0\x01i%\xc5\xf7\x8a\x80PI\t\xb9\xb
9 \xfd`\x01\xc2I\xe6}\x81\x1b\x7f*7\x8a\x1c\'O|\x84\\\xc1\xc...

【问题讨论】:

    标签: python django file file-upload request


    【解决方案1】:

    来自我的一项测试:

    name = 'filename'
    f = file(self.TEST_ROOT + name)
    file_data = {'file':SimpleUploadedFile(f.name,f.read())}
    data = {}
    form = self.TestForm(data,file_data)
    self.assertTrue(form.is_valid())
    

    这个测试通过了。我的代码与您的代码几乎相同,除了我没有将文件传递给表单,而是将文件传递给表单。而且我没有命名传递的参数。这两种差异都没有影响,我已经尝试过了。你的问题是在

    file(settings.MEDIA_ROOT + request.POST['book_pics'])
    

    request.POST['book_pics'] 确实包含文件名,但您的文件不在 MEDIA_ROOT 中。它在 django 放置临时上传文件的位置,或者,如果它是一个小文件,它在内存中。无论哪种方式,您使用代码创建的路径都不会指向该文件。

    如果您尝试通过 ajax 而不是表单发送文件,您可以使用以下解决方案:http://kuhlit.blogspot.de/2011/04/ajax-file-uploads-and-csrf-in-django-13.html 看看该页面中间某处的 django 代码。

    相当复杂,但很有效。

    【讨论】:

    • 我将路径更改为任意内容,Django 调试器给了我一个“没有这样的文件或目录”错误;由此我想我可以推断该文件确实在 MEDIA_ROOT 中。在点击提交之前,我还检查了目录,它就在那里。任何 sddl 想法将不胜感激。
    • 对不起,这里不再猜测。我唯一能告诉你的是 SimpleUploadedFile 很可能不是造成你麻烦的原因。您完全按照我在代码中所做的那样使用它,效果很好。而且您按照文档中的说明使用它,但它仍然没有按照您的意愿行事。
    • 这个具体的例子还是不行。当我制作了一个小部件,它接受一个路径并从中创建一个 SimpleUploadedObject 时,它起作用了,类似于我们的代码,但封装在一个小部件中。
    猜你喜欢
    • 2014-02-05
    • 1970-01-01
    • 2011-01-29
    • 1970-01-01
    • 1970-01-01
    • 2019-01-10
    • 1970-01-01
    • 1970-01-01
    • 2021-12-05
    相关资源
    最近更新 更多