Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test file upload in Django rest framework using PUT?

I would like to write a unit test for a view on a Django REST Framework application. The test should upload a file using PUT, in essence equivalent to

http -a malkarouri PUT http://localhost:8000/data-packages/upload/ka @tmp/hello.py

The code I have written so far is

factory = APIRequestFactory()
request = factory.put(                                                                                                                                                                '/data-packages/upload/ka',
    data,
    content_type='application/octet-stream',
    content_disposition="attachment; filename=data.dump")
force_authenticate(request, user)
view = PackageView.as_view()
response = view(request, "k.py")

which, obviously, does not upload a file. The specific error when running the test is 400:

{u'detail': u'Missing filename. Request should include a Content-Disposition header with a filename parameter.'}

Notably, I am using a request factory to test the view rather than a full client. That is what makes solutions such as the one in this question not work for me.

What is the correct way to set the content disposition header?

like image 442
Muhammad Alkarouri Avatar asked Jun 15 '17 12:06

Muhammad Alkarouri


People also ask

How do I upload to Django REST framework?

So you have two choices: let ModelViewSet and ModelSerializer handle the job and send the request using content-type=multipart/form-data; set the field in ModelSerializer as Base64ImageField (or) Base64FileField and tell your client to encode the file to Base64 and set the content-type=application/json.

Which statement is applicable for CSRF validation in REST framework?

As usual CSRF validation will only apply to any session authenticated views. This means CSRF validation will only occur if the client has been logged in by calling login() .

What is APIRequestFactory?

APIRequestFactory : This is similar to Django's RequestFactory . It allows you to create requests with any http method, which you can then pass on to any view method and compare responses. APIClient : similar to Django's Client . You can GET or POST a URL, and test responses.


2 Answers

from django.core.files.uploadedfile import SimpleUploadedFile
from django.test import TestCase

from rest_framework.test import APIClient


class MyTest(TestCase):
    client_class = APIClient

    def test_it(self):
        file = SimpleUploadedFile("file.txt", b"abc", content_type="text/plain")
        payload = {"file": file}
        response = self.client.post("/some/api/path/", payload, format="multipart")
        self.assertEqual(response.status_code, 201)

        # If you do more calls in this method with the same file then seek to zero
        file.seek(0)
like image 133
hedleyroos Avatar answered Oct 14 '22 07:10

hedleyroos


Hi you need to use the SimpleUploadedFile wrapper for that :

from django.core.files.uploadedfile import SimpleUploadedFile
from django.core.files import File

data = File(open('path/bond-data.dump', 'rb'))
upload_file = SimpleUploadedFile('data.dump', data.read(),content_type='multipart/form-data')
request = factory.put( '/data-packages/upload/ka',
   {'file':upload_file,other_params},
    content_type='application/octet-stream',
    content_disposition="attachment; filename=data.dump")

Ps : I am using APITestCase

like image 10
MaximeK Avatar answered Oct 14 '22 05:10

MaximeK