diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py index 32a726c0b..a459ca27b 100644 --- a/rest_framework/tests/models.py +++ b/rest_framework/tests/models.py @@ -1,4 +1,7 @@ from __future__ import unicode_literals + +import json + from django.db import models from django.utils.translation import ugettext_lazy as _ from rest_framework import serializers @@ -15,6 +18,20 @@ class CustomField(models.CharField): super(CustomField, self).__init__(*args, **kwargs) +class BasicJSONField(models.Field): + def to_python(self, value): + try: + return json.loads(value) + except: + return value + + def get_db_prep_value(self, value, *args, **kwargs): + return json.dumps(value) + + def get_internal_type(self): + return 'TextField' + + class RESTFrameworkModel(models.Model): """ Base for test models that sets app_label, so they play nicely. @@ -164,6 +181,12 @@ class NullableOneToOneSource(RESTFrameworkModel): related_name='nullable_source') +class Project(RESTFrameworkModel): + """A model with a JSON field to test nested serializers.""" + name = models.CharField(max_length=100) + milestones = BasicJSONField() + + # Serializer used to test BasicModel class BasicModelSerializer(serializers.ModelSerializer): class Meta: diff --git a/rest_framework/tests/test_serializer_nested.py b/rest_framework/tests/test_serializer_nested.py index 6d69ffbd0..6ffb83d55 100644 --- a/rest_framework/tests/test_serializer_nested.py +++ b/rest_framework/tests/test_serializer_nested.py @@ -247,6 +247,42 @@ class WritableNestedSerializerObjectTests(TestCase): self.assertEqual(serializer.object, expected_object) +class WritableNestedSerializerFieldTests(TestCase): + """ + Nested serializers should not be assumed to reference nested models. + + In this case, MilestoneSerializer is used to control the data going into + a JSON field, "milestones". + """ + def setUp(self): + class MilestoneSerializer(serializers.Serializer): + name = serializers.CharField() + + class ProjectSerializer(serializers.ModelSerializer): + name = serializers.CharField() + milestones = MilestoneSerializer(many=True) + + class Meta: + model = models.Project + + self.ProjectSerializer = ProjectSerializer + + def test_deserialize(self): + data = { + 'name': 'The Awesome API Project', + 'milestones': [ + {'name': 'Prototype'}, + {'name': 'Minumum viable product'}, + {'name': 'World domination'}, + ], + } + expected_object = models.Project(**data) + serializer = self.ProjectSerializer(data=data) + self.assertTrue(serializer.is_valid()) + obj = serializer.save() + self.assertEqual(obj.milestones, expected_object.milestones) + + class ForeignKeyNestedSerializerUpdateTests(TestCase): def setUp(self): class Artist(object):