From 1227438a39b72e39a63dd0eb26466ce33db00505 Mon Sep 17 00:00:00 2001 From: Jonas Braun Date: Thu, 18 Apr 2013 13:02:00 +0200 Subject: [PATCH] adding test cases and doc entry --- docs/topics/release-notes.md | 1 + rest_framework/relations.py | 5 +++-- rest_framework/tests/relations_pk.py | 27 ++++++++++++++++++++++++++ rest_framework/tests/relations_slug.py | 27 ++++++++++++++++++++++++++ 4 files changed, 58 insertions(+), 2 deletions(-) diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md index 106e7cd55..04cc1890d 100644 --- a/docs/topics/release-notes.md +++ b/docs/topics/release-notes.md @@ -43,6 +43,7 @@ You can determine your currently installed version using `pip freeze`: ### Master * Made Login template more easy to restyle. +* Bugfix: Fix single pks/slugs are not serialized to list when sent to many relation ### 2.2.7 diff --git a/rest_framework/relations.py b/rest_framework/relations.py index a26d502a2..7d43fb378 100644 --- a/rest_framework/relations.py +++ b/rest_framework/relations.py @@ -1,4 +1,5 @@ from __future__ import unicode_literals +from collections import Iterable from django.core.exceptions import ObjectDoesNotExist, ValidationError from django.core.urlresolvers import resolve, get_script_prefix, NoReverseMatch from django import forms @@ -162,8 +163,8 @@ class RelatedField(WritableField): elif value in (None, ''): into[(self.source or field_name)] = None elif self.many: - if isinstance(value, basestring): - into[(self.source or field_name)] = self.from_native(value) + if isinstance(value, basestring) or not isinstance(value, Iterable): + into[(self.source or field_name)] = [self.from_native(value)] else: into[(self.source or field_name)] = [self.from_native(item) for item in value] else: diff --git a/rest_framework/tests/relations_pk.py b/rest_framework/tests/relations_pk.py index f08e18086..abbebe8c3 100644 --- a/rest_framework/tests/relations_pk.py +++ b/rest_framework/tests/relations_pk.py @@ -230,6 +230,33 @@ class PKForeignKeyTests(TestCase): ] self.assertEqual(serializer.data, expected) + def test_reverse_foreign_key_update_only_one_int(self): + data = {'id': 2, 'name': 'target-2', 'sources': 1} + instance = ForeignKeyTarget.objects.get(pk=2) + serializer = ForeignKeyTargetSerializer(instance, data=data) + self.assertTrue(serializer.is_valid()) + # We shouldn't have saved anything to the db yet since save + # hasn't been called. + queryset = ForeignKeyTarget.objects.all() + new_serializer = ForeignKeyTargetSerializer(queryset, many=True) + expected = [ + {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]}, + {'id': 2, 'name': 'target-2', 'sources': []}, + ] + self.assertEqual(new_serializer.data, expected) + + serializer.save() + self.assertEqual(serializer.data, {'id': 2, 'name': 'target-2', 'sources': [1]}) + + # Ensure target 2 is update, and everything else is as expected + queryset = ForeignKeyTarget.objects.all() + serializer = ForeignKeyTargetSerializer(queryset, many=True) + expected = [ + {'id': 1, 'name': 'target-1', 'sources': [2, 3]}, + {'id': 2, 'name': 'target-2', 'sources': [1]}, + ] + self.assertEqual(serializer.data, expected) + def test_foreign_key_create(self): data = {'id': 4, 'name': 'source-4', 'target': 2} serializer = ForeignKeySourceSerializer(data=data) diff --git a/rest_framework/tests/relations_slug.py b/rest_framework/tests/relations_slug.py index 435c821cf..ecc96cf03 100644 --- a/rest_framework/tests/relations_slug.py +++ b/rest_framework/tests/relations_slug.py @@ -106,6 +106,33 @@ class SlugForeignKeyTests(TestCase): ] self.assertEqual(serializer.data, expected) + def test_reverse_foreign_key_update_only_one_instance_as_string(self): + data = {'id': 2, 'name': 'target-2', 'sources': 'source-1'} + instance = ForeignKeyTarget.objects.get(pk=2) + serializer = ForeignKeyTargetSerializer(instance, data=data) + self.assertTrue(serializer.is_valid()) + # We shouldn't have saved anything to the db yet since save + # hasn't been called. + queryset = ForeignKeyTarget.objects.all() + new_serializer = ForeignKeyTargetSerializer(queryset, many=True) + expected = [ + {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']}, + {'id': 2, 'name': 'target-2', 'sources': []}, + ] + self.assertEqual(new_serializer.data, expected) + + serializer.save() + self.assertEqual(serializer.data, {'id': 2, 'name': 'target-2', 'sources': ['source-1']}) + + # Ensure target 2 is update, and everything else is as expected + queryset = ForeignKeyTarget.objects.all() + serializer = ForeignKeyTargetSerializer(queryset, many=True) + expected = [ + {'id': 1, 'name': 'target-1', 'sources': ['source-2', 'source-3']}, + {'id': 2, 'name': 'target-2', 'sources': ['source-1']}, + ] + self.assertEqual(serializer.data, expected) + def test_foreign_key_create(self): data = {'id': 4, 'name': 'source-4', 'target': 'target-2'} serializer = ForeignKeySourceSerializer(data=data)