From b5a3c508f1d74894547bb7a7cc61b3f75da7febe Mon Sep 17 00:00:00 2001 From: GuillaumeCisco Date: Fri, 23 Jun 2017 19:06:08 +0200 Subject: [PATCH 1/7] Fix file+json data post --- parler_rest/fields.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/parler_rest/fields.py b/parler_rest/fields.py index c9afee0..31c7601 100644 --- a/parler_rest/fields.py +++ b/parler_rest/fields.py @@ -3,6 +3,7 @@ Custom serializer fields for nested translations. """ from __future__ import unicode_literals +import json from django.core.exceptions import ImproperlyConfigured from django.utils.translation import ugettext_lazy as _ @@ -24,6 +25,7 @@ class TranslatedFieldsField(serializers.Field): Exposing all translated fields for a TranslatableModel in REST style. """ default_error_messages = dict(serializers.Field.default_error_messages, **{ + 'invalid_json_dump': _("Input is not a valid json dump"), 'invalid': _("Input is not a valid dict"), 'empty': _("This field may not be empty.") }) @@ -129,6 +131,13 @@ def to_internal_value(self, data): if data is None: return + if isinstance(data, basestring): + # try to convert to json + try: + data = json.loads(data) + except: + self.fail('invalid_json_dump') + if not isinstance(data, dict): self.fail('invalid') if not self.allow_empty and len(data) == 0: From af4bc8f66c422dff80c85213c2c4b89e59ec588c Mon Sep 17 00:00:00 2001 From: GuillaumeCisco Date: Mon, 26 Jun 2017 10:21:56 +0200 Subject: [PATCH 2/7] Support python3 --- parler_rest/fields.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/parler_rest/fields.py b/parler_rest/fields.py index 31c7601..b730f8a 100644 --- a/parler_rest/fields.py +++ b/parler_rest/fields.py @@ -131,7 +131,7 @@ def to_internal_value(self, data): if data is None: return - if isinstance(data, basestring): + if isinstance(data, (str, unicode)): # try to convert to json try: data = json.loads(data) From aff1e0fe1b70a68baf2e212823f2eaad9fcd7ade Mon Sep 17 00:00:00 2001 From: GuillaumeCisco Date: Mon, 26 Jun 2017 10:31:43 +0200 Subject: [PATCH 3/7] -mSupport python 2 and python 3 --- parler_rest/fields.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/parler_rest/fields.py b/parler_rest/fields.py index b730f8a..01e08b7 100644 --- a/parler_rest/fields.py +++ b/parler_rest/fields.py @@ -4,6 +4,7 @@ """ from __future__ import unicode_literals import json +from past.builtins import basestring from django.core.exceptions import ImproperlyConfigured from django.utils.translation import ugettext_lazy as _ @@ -131,7 +132,7 @@ def to_internal_value(self, data): if data is None: return - if isinstance(data, (str, unicode)): + if isinstance(data, basestring): # try to convert to json try: data = json.loads(data) From 2501824fe7425e3859ff98e41b15772b9e23c988 Mon Sep 17 00:00:00 2001 From: GuillaumeCisco Date: Mon, 26 Jun 2017 10:48:25 +0200 Subject: [PATCH 4/7] Add missing dependency --- setup.py | 1 + 1 file changed, 1 insertion(+) diff --git a/setup.py b/setup.py index 8edecd2..efe3b4f 100755 --- a/setup.py +++ b/setup.py @@ -48,6 +48,7 @@ def find_version(*parts): install_requires=[ 'django-parler>=1.2', 'djangorestframework>=3.0', + 'future==0.16.0', ], requires=[ 'Django (>=1.4.2)', From 3468dff077ff3048b229d04779a9a075741f87c6 Mon Sep 17 00:00:00 2001 From: GuillaumeCisco Date: Tue, 18 Jul 2017 11:39:40 +0200 Subject: [PATCH 5/7] Use string_types --- parler_rest/fields.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/parler_rest/fields.py b/parler_rest/fields.py index 01e08b7..8aa5501 100644 --- a/parler_rest/fields.py +++ b/parler_rest/fields.py @@ -4,7 +4,7 @@ """ from __future__ import unicode_literals import json -from past.builtins import basestring +from django.utils.six import string_types from django.core.exceptions import ImproperlyConfigured from django.utils.translation import ugettext_lazy as _ @@ -132,7 +132,7 @@ def to_internal_value(self, data): if data is None: return - if isinstance(data, basestring): + if isinstance(data, string_types): # try to convert to json try: data = json.loads(data) From 2d12e1820d8ab79f06bceb2f19995034c4906d43 Mon Sep 17 00:00:00 2001 From: GuillaumeCisco Date: Tue, 18 Jul 2017 11:56:25 +0200 Subject: [PATCH 6/7] Add unit tests for stringified values --- testproj/tests.py | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/testproj/tests.py b/testproj/tests.py index cd4926b..ae12d05 100644 --- a/testproj/tests.py +++ b/testproj/tests.py @@ -98,6 +98,24 @@ def test_translations_validation(self): self.assertTrue(serializer.is_valid(), serializer.errors) six.assertCountEqual(self, serializer.validated_data['translations'], data['translations']) + def test_stringified_translations_validation(self): + data = '''{ + 'country_code': 'FR', + 'translations': { + 'en': { + 'name': "France", + 'url': "http://en.wikipedia.org/wiki/France" + }, + 'es': { + 'name': "Francia", + 'url': "http://es.wikipedia.org/wiki/Francia" + }, + } + }''' + serializer = CountryTranslatedSerializer(data=data) + self.assertTrue(serializer.is_valid(), serializer.errors) + six.assertCountEqual(self, serializer.validated_data['translations'], json.loads(data)['translations']) + def test_translated_fields_validation(self): data = { 'country_code': 'FR', @@ -128,7 +146,7 @@ def test_translations_validation_empty(self): self.assertFalse(serializer.is_valid()) self.assertIn('translations', serializer.errors) - def test_tranlations_saving_on_create(self): + def test_translations_saving_on_create(self): data = { 'country_code': 'FR', 'translations': { From 92e9f0548f971f4e4d51926c458ed1f48af67f8a Mon Sep 17 00:00:00 2001 From: GuillaumeCisco Date: Tue, 18 Jul 2017 12:01:46 +0200 Subject: [PATCH 7/7] Fix stringified test --- testproj/tests.py | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/testproj/tests.py b/testproj/tests.py index ae12d05..29889a6 100644 --- a/testproj/tests.py +++ b/testproj/tests.py @@ -4,6 +4,7 @@ from __future__ import unicode_literals +import json import unittest from django.test import TestCase @@ -23,7 +24,6 @@ class CountryTranslatedSerializerTestCase(TestCase): - # Disable cache as due to automatic db rollback the instance pk # is the same for all tests and with the cache we'd mistakenly # skips saves after the first test. @@ -99,22 +99,23 @@ def test_translations_validation(self): six.assertCountEqual(self, serializer.validated_data['translations'], data['translations']) def test_stringified_translations_validation(self): - data = '''{ - 'country_code': 'FR', - 'translations': { - 'en': { - 'name': "France", - 'url': "http://en.wikipedia.org/wiki/France" - }, - 'es': { - 'name': "Francia", - 'url': "http://es.wikipedia.org/wiki/Francia" - }, + translations = { + 'en': { + 'name': "France", + 'url': "http://en.wikipedia.org/wiki/France" + }, + 'es': { + 'name': "Francia", + 'url': "http://es.wikipedia.org/wiki/Francia" } - }''' + } + data = { + 'country_code': 'FR', + 'translations': json.dumps(translations) + } serializer = CountryTranslatedSerializer(data=data) self.assertTrue(serializer.is_valid(), serializer.errors) - six.assertCountEqual(self, serializer.validated_data['translations'], json.loads(data)['translations']) + six.assertCountEqual(self, serializer.validated_data['translations'], translations) def test_translated_fields_validation(self): data = { @@ -137,7 +138,7 @@ def test_translated_fields_validation(self): self.assertIn('url', serializer.errors['translations']['es']) def test_translations_validation_empty(self): - for empty_value in (None, {}, '', ): + for empty_value in (None, {}, '',): data = { 'country_code': 'FR', 'translations': empty_value @@ -261,7 +262,6 @@ def test_nested_translated_serializer(self): class ParlerRestUtilsTestCase(unittest.TestCase): - def test_automatic_translation_serializer_creation(self): serializer = create_translated_fields_serializer(Country)() assert serializer.fields["name"]