Where/how 替换 Django CBV 中的默认上传处理程序?
Where/how to replace default upload handler in Django CBV?
我正在尝试为基于 class 的视图指定处理文件上传的特定方法。根据 docs 这可以通过以下方式实现:
from django.core.files.uploadhandler import TemporaryFileUploadHandler
request.upload_handlers = [TemporaryFileUploadHandler(request=request)]
如果我在 FormView
的 post
方法中这样指定:
def post(self, request, *args, **kwargs):
request.upload_handlers = [TemporaryFileUploadHandler(request=request)]
return super().post(self, request, *args, **kwargs)
我得到:
AttributeError: You cannot set the upload handlers after the upload has been processed.
类似的变体产生相同的结果:
def post(self, request, *args, **kwargs):
self.request.upload_handlers = [TemporaryFileUploadHandler(request=self.request)]
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
然而,当我在 get
方法中这样做时,这是无效的:
def get(self, request, *args, **kwargs):
request.upload_handlers = [TemporaryFileUploadHandler(request=self.request)]
return super().get(self, request, *args, **kwargs)
如果我上传一个小文件,它仍然使用默认的 django.core.files.uploadhandler.MemoryFileUploadHandler
。
我做错了什么?
编辑
此外,当我尝试反映 note 中的建议时,我得到了相同的结果 AttributeError
:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@csrf_exempt
def post(self, request, *args, **kwargs):
request.upload_handlers = [TemporaryFileUploadHandler(request=request)]
return self._post(request, *args, **kwargs)
@csrf_protect
def _post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
因为您不能更改视图中的上传处理程序,因为它是在您的视图函数之前被调用的东西。
Get 不应收集 post 参数,因此它会相应地运行。
When a user uploads a file, Django passes off the file data to an
upload handler – a small class that handles file data as it gets
uploaded. Upload handlers are initially defined in the
FILE_UPLOAD_HANDLERS setting, which defaults to:
["django.core.files.uploadhandler.MemoryFileUploadHandler",
"django.core.files.uploadhandler.TemporaryFileUploadHandler"]
如果您想要不同的上传处理程序,您可以更改 FILE_UPLOAD_HANDLERS 设置
如果这还不够你可以写下你的custom upload handler
编辑:
Also, request.POST is accessed byCsrfViewMiddleware which is enabled
by default. This means you will need to use csrf_exempt() on your view
to allow you to change the upload handlers.
好的,终于让它工作了(使用@Alasdair 提供的建议)。在 post
上设置 method decorator(crsf_exempt)
是不够的,它需要在 dispatch
上设置。对于将来为此苦苦挣扎的任何人,它是这样的:
from django.views.generic import FormView
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@method_decorator(csrf_exempt, 'dispatch')
class UploadDataSetView(FormView):
def post(self, request, *args, **kwargs):
request.upload_handlers = [TemporaryFileUploadHandler(request=request)]
return self._post(request)
@method_decorator(csrf_protect)
def _post(self, request):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
如果您从模板中删除 {% csrf_token %}
(这正是您想要的),它也会失败。
我正在尝试为基于 class 的视图指定处理文件上传的特定方法。根据 docs 这可以通过以下方式实现:
from django.core.files.uploadhandler import TemporaryFileUploadHandler
request.upload_handlers = [TemporaryFileUploadHandler(request=request)]
如果我在 FormView
的 post
方法中这样指定:
def post(self, request, *args, **kwargs):
request.upload_handlers = [TemporaryFileUploadHandler(request=request)]
return super().post(self, request, *args, **kwargs)
我得到:
AttributeError: You cannot set the upload handlers after the upload has been processed.
类似的变体产生相同的结果:
def post(self, request, *args, **kwargs):
self.request.upload_handlers = [TemporaryFileUploadHandler(request=self.request)]
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
然而,当我在 get
方法中这样做时,这是无效的:
def get(self, request, *args, **kwargs):
request.upload_handlers = [TemporaryFileUploadHandler(request=self.request)]
return super().get(self, request, *args, **kwargs)
如果我上传一个小文件,它仍然使用默认的 django.core.files.uploadhandler.MemoryFileUploadHandler
。
我做错了什么?
编辑
此外,当我尝试反映 note 中的建议时,我得到了相同的结果 AttributeError
:
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@csrf_exempt
def post(self, request, *args, **kwargs):
request.upload_handlers = [TemporaryFileUploadHandler(request=request)]
return self._post(request, *args, **kwargs)
@csrf_protect
def _post(self, request, *args, **kwargs):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
因为您不能更改视图中的上传处理程序,因为它是在您的视图函数之前被调用的东西。
Get 不应收集 post 参数,因此它会相应地运行。
When a user uploads a file, Django passes off the file data to an upload handler – a small class that handles file data as it gets uploaded. Upload handlers are initially defined in the FILE_UPLOAD_HANDLERS setting, which defaults to:
["django.core.files.uploadhandler.MemoryFileUploadHandler", "django.core.files.uploadhandler.TemporaryFileUploadHandler"]
如果您想要不同的上传处理程序,您可以更改 FILE_UPLOAD_HANDLERS 设置
如果这还不够你可以写下你的custom upload handler
编辑:
Also, request.POST is accessed byCsrfViewMiddleware which is enabled by default. This means you will need to use csrf_exempt() on your view to allow you to change the upload handlers.
好的,终于让它工作了(使用@Alasdair 提供的建议)。在 post
上设置 method decorator(crsf_exempt)
是不够的,它需要在 dispatch
上设置。对于将来为此苦苦挣扎的任何人,它是这样的:
from django.views.generic import FormView
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt, csrf_protect
@method_decorator(csrf_exempt, 'dispatch')
class UploadDataSetView(FormView):
def post(self, request, *args, **kwargs):
request.upload_handlers = [TemporaryFileUploadHandler(request=request)]
return self._post(request)
@method_decorator(csrf_protect)
def _post(self, request):
form = self.get_form()
if form.is_valid():
return self.form_valid(form)
else:
return self.form_invalid(form)
如果您从模板中删除 {% csrf_token %}
(这正是您想要的),它也会失败。