From 74fec7eeb4e7e2e593ed5e2213020024264681ce Mon Sep 17 00:00:00 2001 From: Ian Foote Date: Tue, 28 Jan 2014 14:30:46 +0000 Subject: [PATCH 1/3] Import force_bytes on django >= 1.5 --- rest_framework/compat.py | 2 +- rest_framework/tests/test_compat.py | 13 +++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) create mode 100644 rest_framework/tests/test_compat.py diff --git a/rest_framework/compat.py b/rest_framework/compat.py index b69749feb..d283e2f5d 100644 --- a/rest_framework/compat.py +++ b/rest_framework/compat.py @@ -457,7 +457,7 @@ from django.test.client import RequestFactory as DjangoRequestFactory from django.test.client import FakePayload try: # In 1.5 the test client uses force_bytes - from django.utils.encoding import force_bytes_or_smart_bytes + from django.utils.encoding import force_bytes as force_bytes_or_smart_bytes except ImportError: # In 1.3 and 1.4 the test client just uses smart_str from django.utils.encoding import smart_str as force_bytes_or_smart_bytes diff --git a/rest_framework/tests/test_compat.py b/rest_framework/tests/test_compat.py new file mode 100644 index 000000000..4916d19b8 --- /dev/null +++ b/rest_framework/tests/test_compat.py @@ -0,0 +1,13 @@ +import django +from django.test import TestCase + + +class TestCompat(TestCase): + def test_force_bytes_or_smart_bytes(self): + from rest_framework.compat import force_bytes_or_smart_bytes + if django.VERSION >= (1, 5): + from django.utils.encoding import force_bytes + self.assertEqual(force_bytes_or_smart_bytes, force_bytes) + else: + from django.utils.encoding import smart_str + self.assertEqual(force_bytes_or_smart_bytes, smart_str) From 78e4468f0367cc2a3a5cc6f3570a791ad67c90d9 Mon Sep 17 00:00:00 2001 From: Ian Foote Date: Tue, 28 Jan 2014 15:54:50 +0000 Subject: [PATCH 2/3] Add file upload test for APIRequestFactory Remove test_compat --- rest_framework/tests/test_compat.py | 13 ------------- rest_framework/tests/test_testing.py | 9 +++++++++ 2 files changed, 9 insertions(+), 13 deletions(-) delete mode 100644 rest_framework/tests/test_compat.py diff --git a/rest_framework/tests/test_compat.py b/rest_framework/tests/test_compat.py deleted file mode 100644 index 4916d19b8..000000000 --- a/rest_framework/tests/test_compat.py +++ /dev/null @@ -1,13 +0,0 @@ -import django -from django.test import TestCase - - -class TestCompat(TestCase): - def test_force_bytes_or_smart_bytes(self): - from rest_framework.compat import force_bytes_or_smart_bytes - if django.VERSION >= (1, 5): - from django.utils.encoding import force_bytes - self.assertEqual(force_bytes_or_smart_bytes, force_bytes) - else: - from django.utils.encoding import smart_str - self.assertEqual(force_bytes_or_smart_bytes, smart_str) diff --git a/rest_framework/tests/test_testing.py b/rest_framework/tests/test_testing.py index 48b8956b5..71bd8b552 100644 --- a/rest_framework/tests/test_testing.py +++ b/rest_framework/tests/test_testing.py @@ -1,6 +1,8 @@ # -- coding: utf-8 -- from __future__ import unicode_literals +from io import BytesIO + from django.contrib.auth.models import User from django.test import TestCase from rest_framework.compat import patterns, url @@ -143,3 +145,10 @@ class TestAPIRequestFactory(TestCase): force_authenticate(request, user=user) response = view(request) self.assertEqual(response.data['user'], 'example') + + def test_upload_file(self): + # This is a 1x1 black png + simple_png = BytesIO(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\rIDATx\x9cc````\x00\x00\x00\x05\x00\x01\xa5\xf6E@\x00\x00\x00\x00IEND\xaeB`\x82') + simple_png.name = 'test.png' + factory = APIRequestFactory() + factory.post('/', data={'image': simple_png}) From 0043f30cab86f50b61ce265635d503c8212848c4 Mon Sep 17 00:00:00 2001 From: Ian Foote Date: Fri, 31 Jan 2014 09:12:45 +0000 Subject: [PATCH 3/3] Use bytes BOUNDARY on django < 1.5 Django's encode_multipart was updated in django 1.5 to work internally with unicode and convert to bytes. In django >= 1.5 we therefore need to pass the BOUNDARY as unicode. In django < 1.5 we still need to pass it as bytes. --- rest_framework/renderers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py index 2fdd33376..e8afc26d7 100644 --- a/rest_framework/renderers.py +++ b/rest_framework/renderers.py @@ -10,6 +10,7 @@ from __future__ import unicode_literals import copy import json +import django from django import forms from django.core.exceptions import ImproperlyConfigured from django.http.multipartparser import parse_header @@ -597,7 +598,7 @@ class MultiPartRenderer(BaseRenderer): media_type = 'multipart/form-data; boundary=BoUnDaRyStRiNg' format = 'multipart' charset = 'utf-8' - BOUNDARY = 'BoUnDaRyStRiNg' + BOUNDARY = 'BoUnDaRyStRiNg' if django.VERSION >= (1, 5) else b'BoUnDaRyStRiNg' def render(self, data, accepted_media_type=None, renderer_context=None): return encode_multipart(self.BOUNDARY, data)