文件上传

匿名 (未验证) 提交于 2019-12-02 23:32:01
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/boyun58/article/details/89713888

当Django处理文件上载时,文件数据最终放入 request.FILES

#forms.py from django import forms  class UploadFileForm(forms.Form):     title = forms.CharField(max_length=50)     file = forms.FileField() 

处理此表单的视图将接收文件数据request.FILES,该文件数据 是包含 表单中每个FileField( ImageField或其他FileField子类)的键的字典。因此,上述表格中的数据可以作为request.FILES[‘file’]。

request.FILES请求方法是POST,并且发布的请求具有该属性,则应包含数据enctype=“multipart/form-data”。否则, request.FILES将是空的。

#views.py from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import UploadFileForm  # Imaginary function to handle an uploaded file.  def upload_file(request):     if request.method == 'POST':         form = UploadFileForm(request.POST, request.FILES)         if form.is_valid():             handle_uploaded_file(request.FILES['file'])             return HttpResponseRedirect('/success/url/')     else:         form = UploadFileForm()     return render(request, 'upload.html', {'form': form})  def handle_uploaded_file(f):     with open('some/file/name.txt', 'wb+') as destination:         for chunk in f.chunks():             destination.write(chunk) 

使用模型处理上传的文件

如果您使用Model上 FileField将文件保存,则ModelForm 使此过程变得更加容易。调用时 form.save()该文件对象将被保存到由upload_to指定的位置对应的FileField参数:

from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import ModelFormWithFileField  def upload_file(request):     if request.method == 'POST':         form = ModelFormWithFileField(request.POST, request.FILES)         if form.is_valid():             # file is saved             form.save()             return HttpResponseRedirect('/success/url/')     else:         form = ModelFormWithFileField()     return render(request, 'upload.html', {'form': form}) 

如果要手动构建对象,只需将文件对象分配给request.FILES模型中的文件字段

from django.http import HttpResponseRedirect from django.shortcuts import render from .forms import UploadFileForm from .models import ModelWithFileField  def upload_file(request):     if request.method == 'POST':         form = UploadFileForm(request.POST, request.FILES)         if form.is_valid():             instance = ModelWithFileField(file_field=request.FILES['file'])             instance.save()             return HttpResponseRedirect('/success/url/')     else:         form = UploadFileForm()     return render(request, 'upload.html', {'form': form}) 

上传多个文件

#forms.py from django import forms  class FileFieldForm(forms.Form):     file_field = forms.FileField(widget=forms.ClearableFileInput(attrs={'multiple': True})) 
from django.views.generic.edit import FormView from .forms import FileFieldForm  class FileFieldView(FormView):     form_class = FileFieldForm     template_name = 'upload.html'  # Replace with your template.     success_url = '...'  # Replace with your URL or reverse().      def post(self, request, *args, **kwargs):         form_class = self.get_form_class()         form = self.get_form(form_class)         files = request.FILES.getlist('file_field')         if form.is_valid():             for f in files:                 ...  # Do something with each file.             return self.form_valid(form)         else:             return self.form_invalid(form) 

上传处理程序

当用户上传文件时,Django将文件数据传递给上传处理程序 - 一个在上传时处理文件数据的小类。上传处理程序最初在FILE_UPLOAD_HANDLERS设置中定义,默认为:

["django.core.files.uploadhandler.MemoryFileUploadHandler",  "django.core.files.uploadhandler.TemporaryFileUploadHandler"] 

可以编写自定义处理程序来自定义Django处理文件的方式。例如,您可以使用自定义处理程序来强制执行用户级配额,动态压缩数据,渲染进度条,甚至直接将数据发送到另一个存储位置,而无需在本地存储。

存储上传数据的地方

在保存上传的文件之前,需要将数据存储在某处。

默认情况下,如果上传的文件小于2.5兆字节,Django会将上传的全部内容保存在内存中。这意味着保存文件只涉及从内存中读取和写入磁盘,因此非常快。

但是,如果上传的文件太大,Django会将上传的文件写入存储在系统临时目录中的临时文件中。在类似Unix的平台上,这意味着你可以期待Django生成一个类似的文件/tmp/tmpzfp6I6.upload。如果上传足够大,您可以观看此文件的大小增长,因为Django将数据流式传输到磁盘上。

动态修改上传处理程序

有时特定视图需要不同的上载行为。在这些情况下,您可以通过修改基于每个请求覆盖上载处理程序 request.upload_handlers。默认情况下,此列表将包含由其指定的上载处理程序FILE_UPLOAD_HANDLERS,但您可以像修改任何其他列表一样修改列表。

例如,假设您已经编写了一个ProgressBarUploadHandler提供有关上传进度的反馈到某种AJAX小部件。您可以将此处理程序添加到上传处理程序中,如下所示:

request.upload_handlers.insert(0, ProgressBarUploadHandler(request)) 

您可能希望list.insert()在这种情况下使用(而不是 append())因为进度条处理程序需要在任何其他处理程序之前运行。请记住,上传处理程序按顺序处理。

如果要完全替换上传处理程序,只需指定一个新列表:

request.upload_handlers = [ProgressBarUploadHandler(request)] 

只能在访问之前修改上传处理程序,request.POST或者request.FILES- 在上载处理开始后更改上载处理程序没有意义。如果您request.upload_handlers在读取后尝试修改request.POST或request.FILES Django将抛出错误。

因此,应该尽可能早地在视图中修改上传处理程序。

此外,默认情况下启用该request.POST访问 CsrfViewMiddleware权限。这意味着您需要在视图上使用csrf_exempt()以允许您更改上载处理程序。然后,您需要使用 csrf_protect()实际处理请求的函数。请注意,这意味着处理程序可能会在CSRF检查完成之前开始接收文件上载。

from django.views.decorators.csrf import csrf_exempt, csrf_protect  @csrf_exempt def upload_file_view(request):     request.upload_handlers.insert(0, ProgressBarUploadHandler(request))     return _upload_file_view(request)  @csrf_protect def _upload_file_view(request):     ... # Process request 
文章来源: https://blog.csdn.net/boyun58/article/details/89713888
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!