Chr*_* W. 2 python django http-post django-forms
假设Django形式如下......
class MyForm(forms.Form):
attachment = forms.FileField()
Run Code Online (Sandbox Code Playgroud)
我已经看过许多访问上传的Django文件的教程request.FILES['attachment'],但我的印象是,只要有可能,你应该POST通过访问ed数据form.cleaned_data['attachment'].
是否有人会使用request.FILES[]?这些对象是否应包含完全相同的数据?
在HTML中创建表单时,它具有特定的编码(或将数据发送到服务器的方法).默认情况下,编码是application/x-www-form-urlencoded,它实质上在单个字符串中发送表单详细信息.但是,如果要将文件上载到服务器,则需要将编码设置为multipart/form-data(这就是enctype="..."您在关于该主题的所有教程中将注意到的行).这将以多个部分发送数据,每个表单字段一个.有关两种编码如何显示的示例,请参见此处.
当Django遇到multipart/form-data编码时,它会将接收的数据拆分为两个字典:request.FILES字典包含上传的任何文件,同时request.POST包含任何其他表单字段.如果您感兴趣,则处理由文件中的MultiPartParser类完成django/http/__init__.py.
为了说明如何将这些数据呈现给您的代码,我们创建一个简单的应用程序.首先,让我们创建一个由字符字段和文件字段组成的简单表单:
from django import forms
class TestForm(forms.Form):
name = forms.CharField()
file = forms.FileField()
Run Code Online (Sandbox Code Playgroud)
接下来,我们将创建一个简单的视图来创建表单,将任何提交的数据绑定到它,并通过模板呈现它:
from django.shortcuts import render_to_response
from django.template import RequestContext
from forms import TestForm
def show_form(request):
if request.method == 'POST':
form = TestForm(request.POST, request.FILES)
else:
form = TestForm()
context = {
'form': form
}
return render_to_response('show_form.html', context, RequestContext(request))
Run Code Online (Sandbox Code Playgroud)
最后,我们将使用模板显示表单以及有关请求和表单的一些信息:
<html>
<head>
<title>Django forms - file test</title>
</head>
<body>
<form method="post" enctype="multipart/form-data">
{% csrf_token %}
{{ form.as_p }}
<input type="submit" />
</form>
<h2>Request details</h2>
<p>
Request method: {{ request.method }}
<br />
POST data: {{ request.POST|default:"No data" }}
<br />
FILES data: {{ request.FILES|default:"No data" }}
</p>
<h2>Form details</h2>
<p>
Cleaned data: {{ form.cleaned_data|default:"No data" }}
</p>
</body>
</html>
Run Code Online (Sandbox Code Playgroud)
请注意,您需要django.core.context_processors.request在设置中启用上下文处理器才能查看有关请求的详细信息.
如果我们然后启动服务器并将浏览器指向视图,我们会看到我们期望看到的内容 - 空表单,请求模式是GET,并且没有POST,FILES或表单数据.
接下来,在字符字段中输入名称,但不要选择要上载的文件.提交后,我们会收到有关所需文件字段的预期错误.我们感兴趣的是有关请求的信息:
请求方法:POST
POST数据:<QueryDict:{u'csrfmiddlewaretoken':[u'b032358a4dbd71bc3a776c2ef41b09d9'],u'name':[u'Blair'],u'file':[u'']}>
文件数据:没有数据
清理数据:没有数据
由于浏览器没有发送文件信息,Django已将所有表单详细信息放入POST字典中,并将FILES字典留空.由于表单无效,因此没有与之关联的数据.
现在让我们尝试一下没有名字,但要上传一个文件:
请求方法:POST
POST数据:<QueryDict:{u'csrfmiddlewaretoken':[u'b032358a4dbd71bc3a776c2ef41b09d9'],u'name':[u'']}>
文件数据:<MultiValueDict:{u'file':[<InMemoryUploadedFile :image.pdf(application/pdf)>]}>
清理数据:没有数据
现在,提交的数据已在POST和FILES词典之间分配.该文件可以request.FILES['file']通过表单清理数据访问,但不能通过表单清除数据访问,因为表单由于缺少名称而无效.由于我上传的文件很小,它存储在内存中; 超过一定大小(默认为2.5MB)的文件将存储在临时目录中,但您的代码可以处理它们.
最后,让我们尝试使用两个字段的值:
请求方法:POST
POST数据:<QueryDict:{u'csrfmiddlewaretoken':[u'b032358a4dbd71bc3a776c2ef41b09d9'],u'name':[u'Blair']}>
文件数据:<MultiValueDict:{u'file':[< InMemoryUploadedFile:image.pdf(application/pdf)>]}>
清理数据:{'name':u'Blair','file':<InMemoryUploadedFile:image.pdf(application/pdf)>}
由于数据有效并绑定到表单,因此也可以通过cleaned_data表单访问该文件.
通过以下方式访问它有一个潜在的好处request.FILES:如果表单无效,您仍然可以在要求用户更正数据之前将文件保存在某处.这可以防止必须再次上传文件(如果您处理大文件,这在时间和带宽方面可能非常昂贵).如果你只想处理小文件,它不会有太大的区别,但它可能是更好的做法request.FILES.这也是Django文件上传文档的工作方式.
| 归档时间: |
|
| 查看次数: |
1070 次 |
| 最近记录: |