From d48ba1cff76ffceb1d700e9e0c6ccf518a6382da Mon Sep 17 00:00:00 2001
From: Andrey Kaygorodov
Date: Wed, 5 Feb 2014 05:47:27 +0800
Subject: turn of pagination
---
docs/api-guide/pagination.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md
index 0829589f..f86e6ce1 100644
--- a/docs/api-guide/pagination.md
+++ b/docs/api-guide/pagination.md
@@ -102,7 +102,7 @@ You can also set the pagination style on a per-view basis, using the `ListAPIVie
paginate_by_param = 'page_size'
max_paginate_by = 100
-Note that using a `paginate_by` value of `None` will turn off pagination for the view.
+Note that using a `paginate_by` value of `None` will turn off pagination for the view. But if you specified `PAGINATE_BY` and `PAGINATE_BY_PARAM` in your settings file then you have to set both `paginate_by` and `paginate_by_param` to a `None` value in order to turn off pagination for the view.
For more complex requirements such as serialization that differs depending on the requested media type you can override the `.get_paginate_by()` and `.get_pagination_serializer_class()` methods.
--
cgit v1.2.3
From 2d20512d259f51a5a5c2b71b20f98d24e0176f16 Mon Sep 17 00:00:00 2001
From: Andrey Kaygorodov
Date: Wed, 5 Feb 2014 21:10:51 +0800
Subject: #1390, docs, turning of pagination
---
docs/api-guide/pagination.md | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/docs/api-guide/pagination.md b/docs/api-guide/pagination.md
index f86e6ce1..047a0988 100644
--- a/docs/api-guide/pagination.md
+++ b/docs/api-guide/pagination.md
@@ -102,7 +102,8 @@ You can also set the pagination style on a per-view basis, using the `ListAPIVie
paginate_by_param = 'page_size'
max_paginate_by = 100
-Note that using a `paginate_by` value of `None` will turn off pagination for the view. But if you specified `PAGINATE_BY` and `PAGINATE_BY_PARAM` in your settings file then you have to set both `paginate_by` and `paginate_by_param` to a `None` value in order to turn off pagination for the view.
+Note that using a `paginate_by` value of `None` will turn off pagination for the view.
+Note if you use the `PAGINATE_BY_PARAM` settings, you also have to set the `paginate_by_param` attribute in your view to `None` in order to turn off pagination for those requests that contain the `paginate_by_param` parameter.
For more complex requirements such as serialization that differs depending on the requested media type you can override the `.get_paginate_by()` and `.get_pagination_serializer_class()` methods.
--
cgit v1.2.3
From a23059b6f73aaff9709f611826bac892e56663dd Mon Sep 17 00:00:00 2001
From: Miro Hrončok
Date: Wed, 9 Apr 2014 23:35:41 +0200
Subject: Add more TRAILING_PUNCTUATION to work with YAML.
Fixes #1517---
rest_framework/templatetags/rest_framework.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rest_framework/templatetags/rest_framework.py b/rest_framework/templatetags/rest_framework.py
index beb8c5b0..dff176d6 100644
--- a/rest_framework/templatetags/rest_framework.py
+++ b/rest_framework/templatetags/rest_framework.py
@@ -180,7 +180,7 @@ def add_class(value, css_class):
# Bunch of stuff cloned from urlize
-TRAILING_PUNCTUATION = ['.', ',', ':', ';', '.)', '"', "'"]
+TRAILING_PUNCTUATION = ['.', ',', ':', ';', '.)', '"', "']", "'}", "'"]
WRAPPING_PUNCTUATION = [('(', ')'), ('<', '>'), ('[', ']'), ('<', '>'),
('"', '"'), ("'", "'")]
word_split_re = re.compile(r'(\s+)')
--
cgit v1.2.3
From 7ae8409370635ccec7d3c160ea87281f21c9ae11 Mon Sep 17 00:00:00 2001
From: Miro Hrončok
Date: Thu, 10 Apr 2014 01:35:45 +0200
Subject: Allow unicode YAML dump with UnicodeYAMLRenderer
Fixes #1519
---
rest_framework/renderers.py | 11 ++++++++++-
1 file changed, 10 insertions(+), 1 deletion(-)
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py
index 7a7da561..484961ad 100644
--- a/rest_framework/renderers.py
+++ b/rest_framework/renderers.py
@@ -193,6 +193,7 @@ class YAMLRenderer(BaseRenderer):
format = 'yaml'
encoder = encoders.SafeDumper
charset = 'utf-8'
+ ensure_ascii = True
def render(self, data, accepted_media_type=None, renderer_context=None):
"""
@@ -203,7 +204,15 @@ class YAMLRenderer(BaseRenderer):
if data is None:
return ''
- return yaml.dump(data, stream=None, encoding=self.charset, Dumper=self.encoder)
+ return yaml.dump(data, stream=None, encoding=self.charset, Dumper=self.encoder, allow_unicode=not self.ensure_ascii)
+
+
+class UnicodeYAMLRenderer(YAMLRenderer):
+ """
+ Renderer which serializes to YAML.
+ Does *not* apply character escaping for non-ascii characters.
+ """
+ ensure_ascii = False
class TemplateHTMLRenderer(BaseRenderer):
--
cgit v1.2.3
From f68596a7326777f971d9551ff1bfc7176389ea22 Mon Sep 17 00:00:00 2001
From: Miro Hrončok
Date: Thu, 10 Apr 2014 01:58:06 +0200
Subject: Document new UnicodeYAMLRenderer
---
docs/api-guide/renderers.md | 20 ++++++++++++++++++++
1 file changed, 20 insertions(+)
diff --git a/docs/api-guide/renderers.md b/docs/api-guide/renderers.md
index 7798827b..7a3429bf 100644
--- a/docs/api-guide/renderers.md
+++ b/docs/api-guide/renderers.md
@@ -138,6 +138,26 @@ Renders the request data into `YAML`.
Requires the `pyyaml` package to be installed.
+Note that non-ascii characters will be rendered using `\uXXXX` character escape. For example:
+
+ unicode black star: "\u2605"
+
+**.media_type**: `application/yaml`
+
+**.format**: `'.yaml'`
+
+**.charset**: `utf-8`
+
+## UnicodeYAMLRenderer
+
+Renders the request data into `YAML`.
+
+Requires the `pyyaml` package to be installed.
+
+Note that non-ascii characters will not be character escaped. For example:
+
+ unicode black star: ★
+
**.media_type**: `application/yaml`
**.format**: `'.yaml'`
--
cgit v1.2.3
From 0a0e4f22e72badd1d8700a2b253cb27450a5319f Mon Sep 17 00:00:00 2001
From: Ian Foote
Date: Sat, 12 Apr 2014 17:51:02 +0100
Subject: Set GenericForeignKey fields on object before save
* A model with a required GenericForeignKey can be saved if the field is set
---
rest_framework/serializers.py | 3 +++
1 file changed, 3 insertions(+)
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index cb7539e0..1d6097ed 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -16,6 +16,7 @@ import datetime
import inspect
import types
from decimal import Decimal
+from django.contrib.contenttypes.generic import GenericForeignKey
from django.core.paginator import Page
from django.db import models
from django.forms import widgets
@@ -943,6 +944,8 @@ class ModelSerializer(Serializer):
# Forward m2m relations
for field in meta.many_to_many + meta.virtual_fields:
+ if isinstance(field, GenericForeignKey):
+ continue
if field.name in attrs:
m2m_data[field.name] = attrs.pop(field.name)
--
cgit v1.2.3
From 853c7a16c15c7291561bc4b3dfbcad88ea262a18 Mon Sep 17 00:00:00 2001
From: Ian Foote
Date: Sun, 13 Apr 2014 17:26:15 +0100
Subject: Use setattr for adding fields to a new instance
Add test for restoring a GenericForeignKey
---
rest_framework/serializers.py | 18 ++++++++----------
rest_framework/tests/test_genericrelations.py | 18 ++++++++++++++++++
2 files changed, 26 insertions(+), 10 deletions(-)
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 1d6097ed..ea9509bf 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -955,17 +955,15 @@ class ModelSerializer(Serializer):
if isinstance(self.fields.get(field_name, None), Serializer):
nested_forward_relations[field_name] = attrs[field_name]
- # Update an existing instance...
- if instance is not None:
- for key, val in attrs.items():
- try:
- setattr(instance, key, val)
- except ValueError:
- self._errors[key] = self.error_messages['required']
+ # Create an empty instance of the model
+ if instance is None:
+ instance = self.opts.model()
- # ...or create a new instance
- else:
- instance = self.opts.model(**attrs)
+ for key, val in attrs.items():
+ try:
+ setattr(instance, key, val)
+ except ValueError:
+ self._errors[key] = self.error_messages['required']
# Any relations that cannot be set until we've
# saved the model get hidden away on these
diff --git a/rest_framework/tests/test_genericrelations.py b/rest_framework/tests/test_genericrelations.py
index fa09c9e6..46a2d863 100644
--- a/rest_framework/tests/test_genericrelations.py
+++ b/rest_framework/tests/test_genericrelations.py
@@ -131,3 +131,21 @@ class TestGenericRelations(TestCase):
}
]
self.assertEqual(serializer.data, expected)
+
+ def test_restore_object_generic_fk(self):
+ """
+ Ensure an object with a generic foreign key can be restored.
+ """
+
+ class TagSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = Tag
+ exclude = ('content_type', 'object_id')
+
+ serializer = TagSerializer()
+
+ bookmark = Bookmark(url='http://example.com')
+ attrs = {'tagged_item': bookmark, 'tag': 'example'}
+
+ tag = serializer.restore_object(attrs)
+ self.assertEqual(tag.tagged_item, bookmark)
--
cgit v1.2.3
From 4b3eb6e0b0e6412693de126ac92482a276ca9a78 Mon Sep 17 00:00:00 2001
From: Vladislav Vlastovskiy
Date: Mon, 14 Apr 2014 12:21:38 +0400
Subject: Fixed parse file name
---
rest_framework/parsers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py
index f1b3e38d..703cefca 100644
--- a/rest_framework/parsers.py
+++ b/rest_framework/parsers.py
@@ -288,7 +288,7 @@ class FileUploadParser(BaseParser):
try:
meta = parser_context['request'].META
- disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'])
+ disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8'))
return disposition[1]['filename']
except (AttributeError, KeyError):
pass
--
cgit v1.2.3
From 063addabfeb716f54c5784917e92ab6abb635ff5 Mon Sep 17 00:00:00 2001
From: Vladislav Vlastovskiy
Date: Mon, 14 Apr 2014 12:28:41 +0400
Subject: Removed encode from test
Django does not produce such a decoding by default, this test was not honest.---
rest_framework/tests/test_parsers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rest_framework/tests/test_parsers.py b/rest_framework/tests/test_parsers.py
index 7699e10c..ffd6b360 100644
--- a/rest_framework/tests/test_parsers.py
+++ b/rest_framework/tests/test_parsers.py
@@ -96,7 +96,7 @@ class TestFileUploadParser(TestCase):
request = MockRequest()
request.upload_handlers = (MemoryFileUploadHandler(),)
request.META = {
- 'HTTP_CONTENT_DISPOSITION': 'Content-Disposition: inline; filename=file.txt'.encode('utf-8'),
+ 'HTTP_CONTENT_DISPOSITION': 'Content-Disposition: inline; filename=file.txt',
'HTTP_CONTENT_LENGTH': 14,
}
self.parser_context = {'request': request, 'kwargs': {}}
--
cgit v1.2.3
From d474934d365291c28d5741898257cbdd5d0aa9ec Mon Sep 17 00:00:00 2001
From: Vladislav Vlastovskiy
Date: Mon, 14 Apr 2014 13:01:24 +0400
Subject: Fixed return type
From bytes to str---
rest_framework/parsers.py | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py
index 703cefca..d49b17a4 100644
--- a/rest_framework/parsers.py
+++ b/rest_framework/parsers.py
@@ -10,6 +10,7 @@ from django.core.files.uploadhandler import StopFutureHandlers
from django.http import QueryDict
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter
+from django.utils.encoding import force_str
from rest_framework.compat import etree, six, yaml
from rest_framework.exceptions import ParseError
from rest_framework import renderers
@@ -289,6 +290,6 @@ class FileUploadParser(BaseParser):
try:
meta = parser_context['request'].META
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8'))
- return disposition[1]['filename']
+ return force_str(disposition[1]['filename'])
except (AttributeError, KeyError):
pass
--
cgit v1.2.3
From d1f4dfca2061cb552158ac7ea6f2de609989797b Mon Sep 17 00:00:00 2001
From: Vladislav Vlastovskiy
Date: Mon, 14 Apr 2014 13:04:18 +0400
Subject: Removed decode from test filename
---
rest_framework/tests/test_parsers.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rest_framework/tests/test_parsers.py b/rest_framework/tests/test_parsers.py
index ffd6b360..8af90677 100644
--- a/rest_framework/tests/test_parsers.py
+++ b/rest_framework/tests/test_parsers.py
@@ -112,4 +112,4 @@ class TestFileUploadParser(TestCase):
def test_get_filename(self):
parser = FileUploadParser()
filename = parser.get_filename(self.stream, None, self.parser_context)
- self.assertEqual(filename, 'file.txt'.encode('utf-8'))
+ self.assertEqual(filename, 'file.txt')
--
cgit v1.2.3
From 3fe038357267f947eba467f2b7714a782fa93c33 Mon Sep 17 00:00:00 2001
From: Vladislav Vlastovskiy
Date: Mon, 14 Apr 2014 13:21:24 +0400
Subject: Fixed convert bytes to str
Use compact function for convert---
rest_framework/parsers.py | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/rest_framework/parsers.py b/rest_framework/parsers.py
index d49b17a4..4990971b 100644
--- a/rest_framework/parsers.py
+++ b/rest_framework/parsers.py
@@ -10,8 +10,7 @@ from django.core.files.uploadhandler import StopFutureHandlers
from django.http import QueryDict
from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
from django.http.multipartparser import MultiPartParserError, parse_header, ChunkIter
-from django.utils.encoding import force_str
-from rest_framework.compat import etree, six, yaml
+from rest_framework.compat import etree, six, yaml, force_text
from rest_framework.exceptions import ParseError
from rest_framework import renderers
import json
@@ -290,6 +289,6 @@ class FileUploadParser(BaseParser):
try:
meta = parser_context['request'].META
disposition = parse_header(meta['HTTP_CONTENT_DISPOSITION'].encode('utf-8'))
- return force_str(disposition[1]['filename'])
+ return force_text(disposition[1]['filename'])
except (AttributeError, KeyError):
pass
--
cgit v1.2.3
From 617c9825913cfc0cdeaa4405df0b885db0a9ff60 Mon Sep 17 00:00:00 2001
From: Miro Hrončok
Date: Tue, 15 Apr 2014 14:12:09 +0200
Subject: Add test for UnicodeYAMLRenderer
---
rest_framework/tests/test_renderers.py | 13 ++++++++++++-
1 file changed, 12 insertions(+), 1 deletion(-)
diff --git a/rest_framework/tests/test_renderers.py b/rest_framework/tests/test_renderers.py
index c7bf772e..7cb7d0f9 100644
--- a/rest_framework/tests/test_renderers.py
+++ b/rest_framework/tests/test_renderers.py
@@ -12,7 +12,7 @@ from rest_framework.compat import yaml, etree, patterns, url, include, six, Stri
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
- XMLRenderer, JSONPRenderer, BrowsableAPIRenderer, UnicodeJSONRenderer
+ XMLRenderer, JSONPRenderer, BrowsableAPIRenderer, UnicodeJSONRenderer, UnicodeYAMLRenderer
from rest_framework.parsers import YAMLParser, XMLParser
from rest_framework.settings import api_settings
from rest_framework.test import APIRequestFactory
@@ -467,6 +467,17 @@ if yaml:
self.assertTrue(string in content, '%r not in %r' % (string, content))
+ class UnicodeYAMLRendererTests(TestCase):
+ """
+ Tests specific for the Unicode YAML Renderer
+ """
+ def test_proper_encoding(self):
+ obj = {'countries': ['United Kingdom', 'France', 'España']}
+ renderer = UnicodeYAMLRenderer()
+ content = renderer.render(obj, 'application/yaml')
+ self.assertEqual(content.strip(), 'countries: [United Kingdom, France, España]'.encode('utf-8'))
+
+
class XMLRendererTestCase(TestCase):
"""
Tests specific to the XML Renderer
--
cgit v1.2.3
From ef1d65282771c806f68d717d57172597184db26c Mon Sep 17 00:00:00 2001
From: Miro Hrončok
Date: Tue, 15 Apr 2014 14:02:11 +0200
Subject: Introduce tests for urlize_quoted_links() function
---
rest_framework/tests/test_urlizer.py | 38 ++++++++++++++++++++++++++++++++++++
1 file changed, 38 insertions(+)
create mode 100644 rest_framework/tests/test_urlizer.py
diff --git a/rest_framework/tests/test_urlizer.py b/rest_framework/tests/test_urlizer.py
new file mode 100644
index 00000000..3dc8e8fe
--- /dev/null
+++ b/rest_framework/tests/test_urlizer.py
@@ -0,0 +1,38 @@
+from __future__ import unicode_literals
+from django.test import TestCase
+from rest_framework.templatetags.rest_framework import urlize_quoted_links
+import sys
+
+
+class URLizerTests(TestCase):
+ """
+ Test if both JSON and YAML URLs are transformed into links well
+ """
+ def _urlize_dict_check(self, data):
+ """
+ For all items in dict test assert that the value is urlized key
+ """
+ for original, urlized in data.items():
+ assert urlize_quoted_links(original, nofollow=False) == urlized
+
+ def test_json_with_url(self):
+ """
+ Test if JSON URLs are transformed into links well
+ """
+ data = {}
+ data['"url": "http://api/users/1/", '] = \
+ '"url": "http://api/users/1/", '
+ data['"foo_set": [\n "http://api/foos/1/"\n], '] = \
+ '"foo_set": [\n "http://api/foos/1/"\n], '
+ self._urlize_dict_check(data)
+
+ def test_yaml_with_url(self):
+ """
+ Test if YAML URLs are transformed into links well
+ """
+ data = {}
+ data['''{users: 'http://api/users/'}'''] = \
+ '''{users: 'http://api/users/'}'''
+ data['''foo_set: ['http://api/foos/1/']'''] = \
+ '''foo_set: ['http://api/foos/1/']'''
+ self._urlize_dict_check(data)
--
cgit v1.2.3
From a6e525cf3a22a01a4f9924e975ea7288d80ac5ef Mon Sep 17 00:00:00 2001
From: Sergey Sinitsyn
Date: Thu, 24 Apr 2014 15:58:53 +0600
Subject: Add help_text and verbose_name attribute mapping for related field
---
rest_framework/serializers.py | 8 ++++++++
rest_framework/tests/models.py | 3 ++-
rest_framework/tests/test_serializer.py | 26 +++++++++++++++++++++++++-
3 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index ea9509bf..9cb548a5 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -828,6 +828,10 @@ class ModelSerializer(Serializer):
if model_field:
kwargs['required'] = not(model_field.null or model_field.blank)
+ if model_field.help_text is not None:
+ kwargs['help_text'] = model_field.help_text
+ if model_field.verbose_name is not None:
+ kwargs['label'] = model_field.verbose_name
return PrimaryKeyRelatedField(**kwargs)
@@ -1088,6 +1092,10 @@ class HyperlinkedModelSerializer(ModelSerializer):
if model_field:
kwargs['required'] = not(model_field.null or model_field.blank)
+ if model_field.help_text is not None:
+ kwargs['help_text'] = model_field.help_text
+ if model_field.verbose_name is not None:
+ kwargs['label'] = model_field.verbose_name
if self.opts.lookup_field:
kwargs['lookup_field'] = self.opts.lookup_field
diff --git a/rest_framework/tests/models.py b/rest_framework/tests/models.py
index 6c8f2342..0256697a 100644
--- a/rest_framework/tests/models.py
+++ b/rest_framework/tests/models.py
@@ -143,7 +143,8 @@ class ForeignKeyTarget(RESTFrameworkModel):
class ForeignKeySource(RESTFrameworkModel):
name = models.CharField(max_length=100)
- target = models.ForeignKey(ForeignKeyTarget, related_name='sources')
+ target = models.ForeignKey(ForeignKeyTarget, related_name='sources',
+ help_text='Target', verbose_name='Target')
# Nullable ForeignKey
diff --git a/rest_framework/tests/test_serializer.py b/rest_framework/tests/test_serializer.py
index 3ee2b38a..e688c823 100644
--- a/rest_framework/tests/test_serializer.py
+++ b/rest_framework/tests/test_serializer.py
@@ -9,7 +9,8 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers, fields, relations
from rest_framework.tests.models import (HasPositiveIntegerAsChoice, Album, ActionItem, Anchor, BasicModel,
BlankFieldModel, BlogPost, BlogPostComment, Book, CallableDefaultValueModel, DefaultValueModel,
- ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo, RESTFrameworkModel)
+ ManyToManyModel, Person, ReadOnlyManyToManyModel, Photo, RESTFrameworkModel,
+ ForeignKeySource, ManyToManySource)
from rest_framework.tests.models import BasicModelSerializer
import datetime
import pickle
@@ -176,6 +177,16 @@ class PositiveIntegerAsChoiceSerializer(serializers.ModelSerializer):
fields = ['some_integer']
+class ForeignKeySourceSerializer(serializers.ModelSerializer):
+ class Meta:
+ model = ForeignKeySource
+
+
+class HyperlinkedForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
+ class Meta:
+ model = ForeignKeySource
+
+
class BasicTests(TestCase):
def setUp(self):
self.comment = Comment(
@@ -1600,6 +1611,19 @@ class ManyFieldHelpTextTest(TestCase):
self.assertEqual('Some help text.', rel_field.help_text)
+class AttributeMappingOnAutogeneratedRelatedFields(TestCase):
+
+ def test_primary_key_related_field(self):
+ serializer = ForeignKeySourceSerializer()
+ self.assertEqual(serializer.fields['target'].help_text, 'Target')
+ self.assertEqual(serializer.fields['target'].label, 'Target')
+
+ def test_hyperlinked_related_field(self):
+ serializer = HyperlinkedForeignKeySourceSerializer()
+ self.assertEqual(serializer.fields['target'].help_text, 'Target')
+ self.assertEqual(serializer.fields['target'].label, 'Target')
+
+
@unittest.skipUnless(PIL is not None, 'PIL is not installed')
class AttributeMappingOnAutogeneratedFieldsTests(TestCase):
--
cgit v1.2.3
From f4a82dd5dadf95908c96c402f7f68b8e74c7de7a Mon Sep 17 00:00:00 2001
From: Xavier Ordoquy
Date: Thu, 24 Apr 2014 14:33:36 +0200
Subject: Updated the release notes.
---
docs/topics/release-notes.md | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/docs/topics/release-notes.md b/docs/topics/release-notes.md
index 2bc8b2d6..335497ee 100644
--- a/docs/topics/release-notes.md
+++ b/docs/topics/release-notes.md
@@ -40,6 +40,25 @@ You can determine your currently installed version using `pip freeze`:
## 2.3.x series
+### 2.3.x
+
+**Date**: April 2014
+
+* Fix nested serializers linked through a backward foreign key relation
+* Fix bad links for the `BrowsableAPIRenderer` with `YAMLRenderer`
+* Add `UnicodeYAMLRenderer` that extends `YAMLRenderer` with unicode
+* Fix `parse_header` argument convertion
+* Fix mediatype detection under Python3
+* Web browseable API now offers blank option on dropdown when the field is not required
+* `APIException` representation improved for logging purposes
+* Allow source="*" within nested serializers
+* Better support for custom oauth2 provider backends
+* Fix field validation if it's optional and has no value
+* Add `SEARCH_PARAM` and `ORDERING_PARAM`
+* Fix `APIRequestFactory` to support arguments within the url string for GET
+* Allow three transport modes for access tokens when accessing a protected resource
+* Fix `Request`'s `QueryDict` encoding
+
### 2.3.13
**Date**: 6th March 2014
--
cgit v1.2.3
From 82094554e5d267bcb550d3f7be26552befd7a1fe Mon Sep 17 00:00:00 2001
From: Kamil Niski
Date: Sun, 27 Apr 2014 02:54:47 +0200
Subject: Minor typo
---
rest_framework/fields.py | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index 946a5954..8cdc5551 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -289,7 +289,7 @@ class WritableField(Field):
self.validators = self.default_validators + validators
self.default = default if default is not None else self.default
- # Widgets are ony used for HTML forms.
+ # Widgets are only used for HTML forms.
widget = widget or self.widget
if isinstance(widget, type):
widget = widget()
--
cgit v1.2.3
From 4a1ef6d4b15c504881662a2667564394cb333b6b Mon Sep 17 00:00:00 2001
From: Xavier Ordoquy
Date: Sun, 27 Apr 2014 11:52:33 +0200
Subject: Updated Django's versions.
---
.travis.yml | 16 ++++++++--------
tox.ini | 26 +++++++++++++-------------
2 files changed, 21 insertions(+), 21 deletions(-)
diff --git a/.travis.yml b/.travis.yml
index 60b48cba..bd6d2539 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,10 +7,10 @@ python:
- "3.3"
env:
- - DJANGO="https://www.djangoproject.com/download/1.7b1/tarball/"
- - DJANGO="django==1.6.2"
- - DJANGO="django==1.5.5"
- - DJANGO="django==1.4.10"
+ - DJANGO="https://www.djangoproject.com/download/1.7b2/tarball/"
+ - DJANGO="django==1.6.3"
+ - DJANGO="django==1.5.6"
+ - DJANGO="django==1.4.11"
- DJANGO="django==1.3.7"
install:
@@ -23,7 +23,7 @@ install:
- "if [[ ${DJANGO::11} == 'django==1.3' ]]; then pip install django-filter==0.5.4; fi"
- "if [[ ${DJANGO::11} != 'django==1.3' ]]; then pip install django-filter==0.7; fi"
- "if [[ ${TRAVIS_PYTHON_VERSION::1} == '3' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
- - "if [[ ${DJANGO} == 'https://www.djangoproject.com/download/1.7b1/tarball/' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
+ - "if [[ ${DJANGO} == 'https://www.djangoproject.com/download/1.7b2/tarball/' ]]; then pip install -e git+https://github.com/linovia/django-guardian.git@feature/django_1_7#egg=django-guardian-1.2.0; fi"
- export PYTHONPATH=.
script:
@@ -32,13 +32,13 @@ script:
matrix:
exclude:
- python: "2.6"
- env: DJANGO="https://www.djangoproject.com/download/1.7b1/tarball/"
+ env: DJANGO="https://www.djangoproject.com/download/1.7b2/tarball/"
- python: "3.2"
- env: DJANGO="django==1.4.10"
+ env: DJANGO="django==1.4.11"
- python: "3.2"
env: DJANGO="django==1.3.7"
- python: "3.3"
- env: DJANGO="django==1.4.10"
+ env: DJANGO="django==1.4.11"
- python: "3.3"
env: DJANGO="django==1.3.7"
diff --git a/tox.ini b/tox.ini
index 855ab0ce..e2121005 100644
--- a/tox.ini
+++ b/tox.ini
@@ -7,21 +7,21 @@ commands = {envpython} rest_framework/runtests/runtests.py
[testenv:py3.3-django1.7]
basepython = python3.3
-deps = https://www.djangoproject.com/download/1.7b1/tarball/
+deps = https://www.djangoproject.com/download/1.7b2/tarball/
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py3.2-django1.7]
basepython = python3.2
-deps = https://www.djangoproject.com/download/1.7b1/tarball/
+deps = https://www.djangoproject.com/download/1.7b2/tarball/
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py2.7-django1.7]
basepython = python2.7
-deps = https://www.djangoproject.com/download/1.7b1/tarball/
+deps = https://www.djangoproject.com/download/1.7b2/tarball/
django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
@@ -32,21 +32,21 @@ deps = https://www.djangoproject.com/download/1.7b1/tarball/
[testenv:py3.3-django1.6]
basepython = python3.3
-deps = Django==1.6
+deps = Django==1.6.3
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py3.2-django1.6]
basepython = python3.2
-deps = Django==1.6
+deps = Django==1.6.3
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py2.7-django1.6]
basepython = python2.7
-deps = Django==1.6
+deps = Django==1.6.3
django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
@@ -57,7 +57,7 @@ deps = Django==1.6
[testenv:py2.6-django1.6]
basepython = python2.6
-deps = Django==1.6
+deps = Django==1.6.3
django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
@@ -68,21 +68,21 @@ deps = Django==1.6
[testenv:py3.3-django1.5]
basepython = python3.3
-deps = django==1.5.5
+deps = django==1.5.6
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py3.2-django1.5]
basepython = python3.2
-deps = django==1.5.5
+deps = django==1.5.6
django-filter==0.7
defusedxml==0.3
Pillow==2.3.0
[testenv:py2.7-django1.5]
basepython = python2.7
-deps = django==1.5.5
+deps = django==1.5.6
django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
@@ -93,7 +93,7 @@ deps = django==1.5.5
[testenv:py2.6-django1.5]
basepython = python2.6
-deps = django==1.5.5
+deps = django==1.5.6
django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
@@ -104,7 +104,7 @@ deps = django==1.5.5
[testenv:py2.7-django1.4]
basepython = python2.7
-deps = django==1.4.10
+deps = django==1.4.11
django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
@@ -115,7 +115,7 @@ deps = django==1.4.10
[testenv:py2.6-django1.4]
basepython = python2.6
-deps = django==1.4.10
+deps = django==1.4.11
django-filter==0.7
defusedxml==0.3
django-oauth-plus==2.2.1
--
cgit v1.2.3
From 1c777ffe8b67c342bc1b27fefe67d1094a2f6b07 Mon Sep 17 00:00:00 2001
From: Max Peterson
Date: Mon, 28 Apr 2014 12:35:55 +0100
Subject: Ensure Token.generate_key returns a string.
---
rest_framework/authtoken/models.py | 2 +-
rest_framework/tests/test_authentication.py | 6 ++++++
2 files changed, 7 insertions(+), 1 deletion(-)
diff --git a/rest_framework/authtoken/models.py b/rest_framework/authtoken/models.py
index 8eac2cc4..167fa531 100644
--- a/rest_framework/authtoken/models.py
+++ b/rest_framework/authtoken/models.py
@@ -34,7 +34,7 @@ class Token(models.Model):
return super(Token, self).save(*args, **kwargs)
def generate_key(self):
- return binascii.hexlify(os.urandom(20))
+ return binascii.hexlify(os.urandom(20)).decode()
def __unicode__(self):
return self.key
diff --git a/rest_framework/tests/test_authentication.py b/rest_framework/tests/test_authentication.py
index c37d2a51..8773f580 100644
--- a/rest_framework/tests/test_authentication.py
+++ b/rest_framework/tests/test_authentication.py
@@ -195,6 +195,12 @@ class TokenAuthTests(TestCase):
token = Token.objects.create(user=self.user)
self.assertTrue(bool(token.key))
+ def test_generate_key_returns_string(self):
+ """Ensure generate_key returns a string"""
+ token = Token()
+ key = token.generate_key()
+ self.assertTrue(isinstance(key, str))
+
def test_token_login_json(self):
"""Ensure token login view using JSON POST works."""
client = APIClient(enforce_csrf_checks=True)
--
cgit v1.2.3
From 170fa10ae0f2b531a8011be33cc9417b9f71e698 Mon Sep 17 00:00:00 2001
From: Max Peterson
Date: Mon, 28 Apr 2014 13:10:34 +0100
Subject: Python < 3 compatibility.
---
rest_framework/tests/test_authentication.py | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/rest_framework/tests/test_authentication.py b/rest_framework/tests/test_authentication.py
index 8773f580..34ce1b7a 100644
--- a/rest_framework/tests/test_authentication.py
+++ b/rest_framework/tests/test_authentication.py
@@ -199,7 +199,13 @@ class TokenAuthTests(TestCase):
"""Ensure generate_key returns a string"""
token = Token()
key = token.generate_key()
- self.assertTrue(isinstance(key, str))
+ try:
+ # added in Python < 3
+ base = unicode
+ except NameError:
+ # added in Python >= 3
+ base = str
+ self.assertTrue(isinstance(key, base))
def test_token_login_json(self):
"""Ensure token login view using JSON POST works."""
--
cgit v1.2.3
From 73597a16a2a6a388a08af923a1da8aa71d2f2848 Mon Sep 17 00:00:00 2001
From: Max Peterson
Date: Mon, 28 Apr 2014 13:13:51 +0100
Subject: Better Python < 3 compatibility.
---
rest_framework/tests/test_authentication.py | 10 ++--------
1 file changed, 2 insertions(+), 8 deletions(-)
diff --git a/rest_framework/tests/test_authentication.py b/rest_framework/tests/test_authentication.py
index 34ce1b7a..a1c43d9c 100644
--- a/rest_framework/tests/test_authentication.py
+++ b/rest_framework/tests/test_authentication.py
@@ -19,7 +19,7 @@ from rest_framework.authentication import (
OAuth2Authentication
)
from rest_framework.authtoken.models import Token
-from rest_framework.compat import patterns, url, include
+from rest_framework.compat import patterns, url, include, six
from rest_framework.compat import oauth2_provider, oauth2_provider_scope
from rest_framework.compat import oauth, oauth_provider
from rest_framework.test import APIRequestFactory, APIClient
@@ -199,13 +199,7 @@ class TokenAuthTests(TestCase):
"""Ensure generate_key returns a string"""
token = Token()
key = token.generate_key()
- try:
- # added in Python < 3
- base = unicode
- except NameError:
- # added in Python >= 3
- base = str
- self.assertTrue(isinstance(key, base))
+ self.assertTrue(isinstance(key, six.string_types))
def test_token_login_json(self):
"""Ensure token login view using JSON POST works."""
--
cgit v1.2.3
From 5e8f05a8de410125d6df7a8e27f61e94176a8897 Mon Sep 17 00:00:00 2001
From: dpetzel
Date: Mon, 28 Apr 2014 13:51:50 -0400
Subject: very minor typo in code example
---
docs/api-guide/permissions.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/api-guide/permissions.md b/docs/api-guide/permissions.md
index 6a0f48f4..50f669a2 100644
--- a/docs/api-guide/permissions.md
+++ b/docs/api-guide/permissions.md
@@ -56,7 +56,7 @@ You can also set the authentication policy on a per-view, or per-viewset basis,
using the `APIView` class based views.
from rest_framework.permissions import IsAuthenticated
- from rest_framework.responses import Response
+ from rest_framework.response import Response
from rest_framework.views import APIView
class ExampleView(APIView):
--
cgit v1.2.3
From d8cb85ef8fb0a0804d9b2c09d909ad99f69301c8 Mon Sep 17 00:00:00 2001
From: Laurent Bristiel
Date: Mon, 28 Apr 2014 22:00:36 +0200
Subject: typo
---
docs/api-guide/generic-views.md | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/docs/api-guide/generic-views.md b/docs/api-guide/generic-views.md
index fb927ea8..7d06f246 100755
--- a/docs/api-guide/generic-views.md
+++ b/docs/api-guide/generic-views.md
@@ -70,7 +70,7 @@ The following attributes control the basic view behavior.
**Shortcuts**:
-* `model` - This shortcut may be used instead of setting either (or both) of the `queryset`/`serializer_class` attributes, although using the explicit style is generally preferred. If used instead of `serializer_class`, then then `DEFAULT_MODEL_SERIALIZER_CLASS` setting will determine the base serializer class. Note that `model` is only ever used for generating a default queryset or serializer class - the `queryset` and `serializer_class` attributes are always preferred if provided.
+* `model` - This shortcut may be used instead of setting either (or both) of the `queryset`/`serializer_class` attributes, although using the explicit style is generally preferred. If used instead of `serializer_class`, then `DEFAULT_MODEL_SERIALIZER_CLASS` setting will determine the base serializer class. Note that `model` is only ever used for generating a default queryset or serializer class - the `queryset` and `serializer_class` attributes are always preferred if provided.
**Pagination**:
--
cgit v1.2.3