aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/api-guide/relations.md14
-rw-r--r--docs/topics/credits.md2
-rw-r--r--docs/tutorial/4-authentication-and-permissions.md4
-rw-r--r--rest_framework/serializers.py7
-rw-r--r--rest_framework/templates/rest_framework/base.html2
-rw-r--r--rest_framework/tests/test_renderers.py13
-rw-r--r--rest_framework/tests/test_serializer.py27
-rw-r--r--rest_framework/utils/encoders.py3
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,