diff options
| -rw-r--r-- | docs/api-guide/relations.md | 14 | ||||
| -rw-r--r-- | docs/topics/credits.md | 2 | ||||
| -rw-r--r-- | docs/tutorial/4-authentication-and-permissions.md | 4 | ||||
| -rw-r--r-- | rest_framework/serializers.py | 7 | ||||
| -rw-r--r-- | rest_framework/templates/rest_framework/base.html | 2 | ||||
| -rw-r--r-- | rest_framework/tests/test_renderers.py | 13 | ||||
| -rw-r--r-- | rest_framework/tests/test_serializer.py | 27 | ||||
| -rw-r--r-- | rest_framework/utils/encoders.py | 3 |
8 files changed, 62 insertions, 10 deletions
diff --git a/docs/api-guide/relations.md b/docs/api-guide/relations.md index 5ec4b22f..b9d96b5e 100644 --- a/docs/api-guide/relations.md +++ b/docs/api-guide/relations.md @@ -54,7 +54,7 @@ Would serialize to the following representation. { 'album_name': 'Things We Lost In The Fire', - 'artist': 'Low' + 'artist': 'Low', 'tracks': [ '1: Sunflower', '2: Whitetail', @@ -86,7 +86,7 @@ Would serialize to a representation like this: { 'album_name': 'The Roots', - 'artist': 'Undun' + 'artist': 'Undun', 'tracks': [ 89, 90, @@ -121,7 +121,7 @@ Would serialize to a representation like this: { 'album_name': 'Graceland', - 'artist': 'Paul Simon' + 'artist': 'Paul Simon', 'tracks': [ 'http://www.example.com/api/tracks/45/', 'http://www.example.com/api/tracks/46/', @@ -159,7 +159,7 @@ Would serialize to a representation like this: { 'album_name': 'Dear John', - 'artist': 'Loney Dear' + 'artist': 'Loney Dear', 'tracks': [ 'Airport Surroundings', 'Everything Turns to You', @@ -194,7 +194,7 @@ Would serialize to a representation like this: { 'album_name': 'The Eraser', - 'artist': 'Thom Yorke' + 'artist': 'Thom Yorke', 'track_listing': 'http://www.example.com/api/track_list/12/', } @@ -234,7 +234,7 @@ Would serialize to a nested representation like this: { 'album_name': 'The Grey Album', - 'artist': 'Danger Mouse' + 'artist': 'Danger Mouse', 'tracks': [ {'order': 1, 'title': 'Public Service Announcement'}, {'order': 2, 'title': 'What More Can I Say'}, @@ -271,7 +271,7 @@ This custom field would then serialize to the following representation. { 'album_name': 'Sometimes I Wish We Were an Eagle', - 'artist': 'Bill Callahan' + 'artist': 'Bill Callahan', 'tracks': [ 'Track 1: Jim Cain (04:39)', 'Track 2: Eid Ma Clack Shaw (04:19)', diff --git a/docs/topics/credits.md b/docs/topics/credits.md index 586bb0f0..9a20028c 100644 --- a/docs/topics/credits.md +++ b/docs/topics/credits.md @@ -171,6 +171,7 @@ The following people have helped make REST framework great. * Tai Lee - [mrmachine] * Markus Kaiserswerth - [mkai] * Henry Clifford - [hcliff] +* Thomas Badaud - [badale] Many thanks to everyone who's contributed to the project. @@ -378,3 +379,4 @@ You can also contact [@_tomchristie][twitter] directly on twitter. [mrmachine]: https://github.com/mrmachine [mkai]: https://github.com/mkai [hcliff]: https://github.com/hcliff +[badale]: https://github.com/badale diff --git a/docs/tutorial/4-authentication-and-permissions.md b/docs/tutorial/4-authentication-and-permissions.md index 393d879a..510aa243 100644 --- a/docs/tutorial/4-authentication-and-permissions.md +++ b/docs/tutorial/4-authentication-and-permissions.md @@ -75,6 +75,10 @@ We'll also add a couple of views. We'd like to just use read-only views for the class UserDetail(generics.RetrieveAPIView): queryset = User.objects.all() serializer_class = UserSerializer + +Make sure to also import the `UserSerializer` class + + from snippets.serializers import UserSerializer Finally we need to add those views into the API, by referencing them from the URL conf. diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index fa5ac143..4210d058 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -262,10 +262,13 @@ class BaseSerializer(WritableField): for field_name, field in self.fields.items(): if field_name in self._errors: continue + + source = field.source or field_name + if self.partial and source not in attrs: + continue try: validate_method = getattr(self, 'validate_%s' % field_name, None) if validate_method: - source = field.source or field_name attrs = validate_method(attrs, source) except ValidationError as err: self._errors[field_name] = self._errors.get(field_name, []) + list(err.messages) @@ -912,7 +915,7 @@ class ModelSerializer(Serializer): def save_object(self, obj, **kwargs): """ - Save the deserialized object and return it. + Save the deserialized object. """ if getattr(obj, '_nested_forward_relations', None): # Nested relationships need to be saved before we can save the diff --git a/rest_framework/templates/rest_framework/base.html b/rest_framework/templates/rest_framework/base.html index 33be36db..7ab17dff 100644 --- a/rest_framework/templates/rest_framework/base.html +++ b/rest_framework/templates/rest_framework/base.html @@ -110,7 +110,9 @@ <div class="content-main"> <div class="page-header"><h1>{{ name }}</h1></div> + {% block description %} {{ description }} + {% endblock %} <div class="request-info" style="clear: both" > <pre class="prettyprint"><b>{{ request.method }}</b> {{ request.get_full_path }}</pre> </div> diff --git a/rest_framework/tests/test_renderers.py b/rest_framework/tests/test_renderers.py index df6f4aa6..76299a89 100644 --- a/rest_framework/tests/test_renderers.py +++ b/rest_framework/tests/test_renderers.py @@ -328,7 +328,7 @@ if yaml: class YAMLRendererTests(TestCase): """ - Tests specific to the JSON Renderer + Tests specific to the YAML Renderer """ def test_render(self): @@ -354,6 +354,17 @@ if yaml: data = parser.parse(StringIO(content)) self.assertEqual(obj, data) + def test_render_decimal(self): + """ + Test YAML decimal rendering. + """ + renderer = YAMLRenderer() + content = renderer.render({'field': Decimal('111.2')}, 'application/yaml') + self.assertYAMLContains(content, "field: '111.2'") + + def assertYAMLContains(self, content, string): + self.assertTrue(string in content, '%r not in %r' % (string, content)) + class XMLRendererTestCase(TestCase): """ diff --git a/rest_framework/tests/test_serializer.py b/rest_framework/tests/test_serializer.py index 29c08fbc..1f85a474 100644 --- a/rest_framework/tests/test_serializer.py +++ b/rest_framework/tests/test_serializer.py @@ -511,6 +511,33 @@ class CustomValidationTests(TestCase): self.assertFalse(serializer.is_valid()) self.assertEqual(serializer.errors, {'email': ['Enter a valid email address.']}) + def test_partial_update(self): + """ + Make sure that validate_email isn't called when partial=True and email + isn't found in data. + """ + initial_data = { + 'email': 'tom@example.com', + 'content': 'A test comment', + 'created': datetime.datetime(2012, 1, 1) + } + + serializer = self.CommentSerializerWithFieldValidator(data=initial_data) + self.assertEqual(serializer.is_valid(), True) + instance = serializer.object + + new_content = 'An *updated* test comment' + partial_data = { + 'content': new_content + } + + serializer = self.CommentSerializerWithFieldValidator(instance=instance, + data=partial_data, + partial=True) + self.assertEqual(serializer.is_valid(), True) + instance = serializer.object + self.assertEqual(instance.content, new_content) + class PositiveIntegerAsChoiceTests(TestCase): def test_positive_integer_in_json_is_correctly_parsed(self): diff --git a/rest_framework/utils/encoders.py b/rest_framework/utils/encoders.py index 7efd5417..35ad206b 100644 --- a/rest_framework/utils/encoders.py +++ b/rest_framework/utils/encoders.py @@ -89,6 +89,9 @@ else: node.flow_style = best_style return node + SafeDumper.add_representer(decimal.Decimal, + SafeDumper.represent_decimal) + SafeDumper.add_representer(SortedDict, yaml.representer.SafeRepresenter.represent_dict) SafeDumper.add_representer(DictWithMetadata, |
