From ad7aa8fe485580e1bdff53d39fe3ea282d908a04 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Sun, 17 Nov 2013 01:27:16 +0100 Subject: [PATCH 1/2] =?UTF-8?q?Fixed=20the=20nested=20model=20serializers?= =?UTF-8?q?=20in=20case=20of=20the=20related=5Fname=20isn=E2=80=99t=20set.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rest_framework/serializers.py | 2 +- .../tests/test_serializer_nested.py | 35 +++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index 163abf4f0..e20e582ec 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -872,7 +872,7 @@ class ModelSerializer(Serializer): # Reverse fk or one-to-one relations for (obj, model) in meta.get_all_related_objects_with_model(): - field_name = obj.field.related_query_name() + field_name = obj.get_accessor_name() if field_name in attrs: related_data[field_name] = attrs.pop(field_name) diff --git a/rest_framework/tests/test_serializer_nested.py b/rest_framework/tests/test_serializer_nested.py index 029f8bffd..7114a0603 100644 --- a/rest_framework/tests/test_serializer_nested.py +++ b/rest_framework/tests/test_serializer_nested.py @@ -6,6 +6,7 @@ Doesn't cover model serializers. from __future__ import unicode_literals from django.test import TestCase from rest_framework import serializers +from . import models class WritableNestedSerializerBasicTests(TestCase): @@ -311,3 +312,37 @@ class ForeignKeyNestedSerializerUpdateTests(TestCase): serializer = self.AlbumSerializer(instance=original, data=data) self.assertEqual(serializer.is_valid(), True) self.assertEqual(serializer.object, expected) + + +class NestedModelSerializerUpdateTests(TestCase): + def test_second_nested_level(self): + john = models.Person.objects.create(name="john") + + post = john.blogpost_set.create(title="Test blog post") + post.blogpostcomment_set.create(text="I hate this blog post") + post.blogpostcomment_set.create(text="I love this blog post") + + class BlogPostCommentSerializer(serializers.ModelSerializer): + class Meta: + model = models.BlogPostComment + + class BlogPostSerializer(serializers.ModelSerializer): + comments = BlogPostCommentSerializer(many=True, source='blogpostcomment_set') + class Meta: + model = models.BlogPost + fields = ('id', 'title', 'comments') + + class PersonSerializer(serializers.ModelSerializer): + posts = BlogPostSerializer(many=True, source='blogpost_set') + class Meta: + model = models.Person + fields = ('id', 'name', 'age', 'posts') + + serialize = PersonSerializer(instance=john) + deserialize = PersonSerializer(data=serialize.data, instance=john) + self.assertTrue(deserialize.is_valid()) + + result = deserialize.object + result.save() + self.assertEqual(result.id, john.id) + From a8b15f4290f4bad17d0dd599b8d5c29c155b89e5 Mon Sep 17 00:00:00 2001 From: Xavier Ordoquy Date: Mon, 18 Nov 2013 15:06:39 +0100 Subject: [PATCH 2/2] =?UTF-8?q?Another=20fix=20for=20nested=20writable=20s?= =?UTF-8?q?erializers=20in=20case=20of=20the=20related=5Fname=20isn?= =?UTF-8?q?=E2=80=99t=20set=20on=20the=20ForeignKey.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- rest_framework/serializers.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index e20e582ec..5059c71b3 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -940,11 +940,12 @@ class ModelSerializer(Serializer): del(obj._m2m_data) if getattr(obj, '_related_data', None): + related_fields = dict(((f.get_accessor_name(), f) for f, m in obj._meta.get_all_related_objects_with_model())) for accessor_name, related in obj._related_data.items(): if isinstance(related, RelationsList): # Nested reverse fk relationship for related_item in related: - fk_field = obj._meta.get_field_by_name(accessor_name)[0].field.name + fk_field = related_fields[accessor_name].field.name setattr(related_item, fk_field, obj) self.save_object(related_item)