2016-11-06 1 views
2

J'ai développé une API (Python 3.5, Django 1.10, DRF 3.4.2) qui télécharge un fichier vidéo sur mon chemin média lorsque je le demande depuis mon interface utilisateur. Cette partie fonctionne bien. J'essaye d'écrire un test pour cette fonctionnalité mais je n'arrive pas à l'exécuter correctement.Comment générer une requête de téléchargement (test) de fichier avec APIRequestFactory de Django REST Framework?

#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) 

et

#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)) 

Dans ce test, je dois utiliser un fichier vidéo existant ('media/testfiles/vid.mp4') et le télécharger depuis que je dois tester quelques traitements sur la données vidéo après: c'est pourquoi j'ai réinitialiser le MEDIA_ROOT en utilisant mkdtemp.

Le test échoue car le fichier n'est pas téléchargé. Dans le def put de mon views.py, quand j'imprime request je reçois <rest_framework.request.Request object at 0x10f25f048> et quand j'imprime request.data je reçois rien. Mais si je supprime le FileUploadParser à mon avis et que j'utilise request = factory.put('file_upload/' + filename, {'filename': filename}, format="multipart") dans mon test, je reçois <QueryDict: {'filename': ['vid']}> lorsque j'imprime request.data. Donc, ma conclusion est que la demande que je génère avec APIRequestFactory est incorrecte. Le FileUploadParser n'est pas en mesure d'extraire le fichier brut de celui-ci.

D'où ma question: Comment générer une requête de téléchargement (test) de fichier avec APIRequestFactory de Django REST Framework?

Plusieurs personnes ont posé des questions proches de celle-ci sur le SO mais je n'ai pas eu de succès avec les réponses proposées.

Toute aide à cet égard sera grandement appréciée!

Répondre

4

Tout va bien maintenant! En passant de APIRequestFactory à APIClient, j'ai réussi à faire fonctionner mon test.

Mon nouveau 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))