问题描述
我已经开发了一个API(Python 3.5,Django 1.10,DRF 3.4.2),当我从用户界面请求视频文件时,该视频文件会上传到我的媒体路径中。那部分工作正常。我尝试为此功能编写测试,但无法使其成功运行。
I have developed an API (Python 3.5, Django 1.10, DRF 3.4.2) that uploads a video file to my media path when I request it from my UI. That part is working fine. I try to write a test for this feature but cannot get it to run successfully.
#views.py
import os
from rest_framework import views, parsers, response
from django.conf import settings
class FileUploadView(views.APIView):
parser_classes = (parsers.FileUploadParser,)
def put(self, request, filename):
file = request.data['file']
handle_uploaded_file(file, filename)
return response.Response(status=204)
def handle_uploaded_file(file, filename):
dir_name = settings.MEDIA_ROOT + '/scene/' + filename + '/cam1'
new_filename = 'orig.mp4'
if not os.path.exists(dir_name):
os.makedirs(dir_name)
file_path = os.path.join(dir_name, new_filename)
with open(file_path, 'wb+') as destination:
for chunk in file.chunks():
destination.write(chunk)
和
#test.py
import tempfile
import os
from django.test import TestCase
from django.conf import settings
from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile
from rest_framework.test import APIRequestFactory
from myapp.views import FileUploadView
class UploadVideoTestCase(TestCase):
def setUp(self):
settings.MEDIA_ROOT = tempfile.mkdtemp(suffix=None, prefix=None, dir=None)
def test_video_uploaded(self):
"""Video uploaded"""
filename = 'vid'
file = File(open('media/testfiles/vid.mp4', 'rb'))
uploaded_file = SimpleUploadedFile(filename, file.read(), 'video')
factory = APIRequestFactory()
request = factory.put('file_upload/'+filename,
{'file': uploaded_file}, format='multipart')
view = FileUploadView.as_view()
response = view(request, filename)
print(response)
dir_name = settings.MEDIA_ROOT + '/scene/' + filename + '/cam1'
new_filename = 'orig.mp4'
file_path = os.path.join(dir_name, new_filename)
self.assertTrue(os.path.exists(file_path))
在此测试中,我需要使用现有的视频文件( media / testfiles / vid.mp4)并上传它,因为我需要在之后的视频数据:这就是为什么我使用 mkdtemp
重置 MEDIA_ROOT
的原因。
In this test, I need to use an existing video file ('media/testfiles/vid.mp4') and upload it since I need to test some processings on the video data after: that's why I reset the MEDIA_ROOT
using mkdtemp
.
由于文件未上传,因此测试失败。当我打印请求$ c时,在我的
views.py
的 def中放置
$ c>我得到< rest_framework.request.Request对象位于0x10f25f048>
,当我打印 request.data
时,什么都没得到。但是,如果我在视图中删除 FileUploadParser
并使用 request = factory.put('file_upload /'+ filename,{'filename':filename} ,在我的测试中为format = multipart)
,我得到< QueryDict:{'filename':['vid']}>
当我打印 request.data
。
The test fails since the file is not uploaded. In the def put
of my views.py
, when I print request
I get <rest_framework.request.Request object at 0x10f25f048>
and when I print request.data
I get nothing. But if I remove the FileUploadParser
in my view and use request = factory.put('file_upload/' + filename, {'filename': filename}, format="multipart")
in my test, I get <QueryDict: {'filename': ['vid']}>
when I print request.data
.
所以我的结论是我用 APIRequestFactory 不正确。 FileUploadParser
无法从其中检索原始文件。
So my conclusion is that the request I generate with APIRequestFactory
is incorrect. The FileUploadParser
is not able to retrieve the raw file from it.
因此,我的问题是:如何使用Django REST Framework的APIRequestFactory生成文件上传(测试)请求?
几个人在SO上提出了与此问题类似的问题,但我没有成功
Several people have asked questions close to this one on SO but I had no success with the proposed answers.
在此问题上的任何帮助将不胜感激!
Any help on that matter will be much appreciated!
推荐答案
现在可以了!从APIRequestFactory切换到APIClient,我设法运行了我的测试。
It's alright now! Switching from APIRequestFactory to APIClient, I managed to have my test running.
我的新test.py:
My new test.py:
import os
import tempfile
from django.conf import settings
from django.core.files import File
from django.core.files.uploadedfile import SimpleUploadedFile
from django.urls import reverse
from rest_framework.test import APITestCase, APIClient
from django.contrib.auth.models import User
class UploadVideoTestCase(APITestCase):
def setUp(self):
settings.MEDIA_ROOT = tempfile.mkdtemp()
User.objects.create_user('michel')
def test_video_uploaded(self):
"""Video uploaded"""
filename = 'vid'
file = File(open('media/testfiles/vid.mp4', 'rb'))
uploaded_file = SimpleUploadedFile(filename, file.read(),
content_type='multipart/form-data')
client = APIClient()
user = User.objects.get(username='michel')
client.force_authenticate(user=user)
url = reverse('file_upload:upload_view', kwargs={'filename': filename})
client.put(url, {'file': uploaded_file}, format='multipart')
dir_name = settings.MEDIA_ROOT + '/scene/' + filename + '/cam1'
new_filename = 'orig.mp4'
file_path = os.path.join(dir_name, new_filename)
self.assertTrue(os.path.exists(file_path))
这篇关于如何使用Django REST Framework的APIRequestFactory生成文件上传(测试)请求?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!