aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
authorPhilip Douglas2013-08-16 07:15:09 -0700
committerPhilip Douglas2013-08-16 07:15:09 -0700
commitef7ce344865938bea285a408a7cc415a7b90a83c (patch)
tree1bfa78c86e422f81cf836319d91c626c763d5b24 /rest_framework
parentc058ab36b13a6979c57760d9af2eb21ec3165e7d (diff)
parentc1ccd8b5b5aef1bd209862f9431c9c03e25ae755 (diff)
downloaddjango-rest-framework-ef7ce344865938bea285a408a7cc415a7b90a83c.tar.bz2
Merge pull request #3 from tomchristie/master
Update to latest
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/__init__.py2
-rw-r--r--rest_framework/fields.py2
-rw-r--r--rest_framework/filters.py5
-rw-r--r--rest_framework/serializers.py6
-rw-r--r--rest_framework/templates/rest_framework/base.html2
-rw-r--r--rest_framework/tests/test_throttling.py33
-rw-r--r--rest_framework/throttling.py3
-rw-r--r--rest_framework/views.py2
8 files changed, 44 insertions, 11 deletions
diff --git a/rest_framework/__init__.py b/rest_framework/__init__.py
index 776618ac..087808e0 100644
--- a/rest_framework/__init__.py
+++ b/rest_framework/__init__.py
@@ -1,4 +1,4 @@
-__version__ = '2.3.6'
+__version__ = '2.3.7'
VERSION = __version__ # synonym
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index f9931887..add9d224 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -924,7 +924,7 @@ class ImageField(FileField):
if f is None:
return None
- from compat import Image
+ from rest_framework.compat import Image
assert Image is not None, 'PIL must be installed for ImageField support'
# We need to get a file object for PIL. We might have a path or we might
diff --git a/rest_framework/filters.py b/rest_framework/filters.py
index c058bc71..4079e1bd 100644
--- a/rest_framework/filters.py
+++ b/rest_framework/filters.py
@@ -109,8 +109,7 @@ class OrderingFilter(BaseFilterBackend):
def get_ordering(self, request):
"""
- Search terms are set by a ?search=... query parameter,
- and may be comma and/or whitespace delimited.
+ Ordering is set by a comma delimited ?ordering=... query parameter.
"""
params = request.QUERY_PARAMS.get(self.ordering_param)
if params:
@@ -134,7 +133,7 @@ class OrderingFilter(BaseFilterBackend):
ordering = self.remove_invalid_fields(queryset, ordering)
if not ordering:
- # Use 'ordering' attribtue by default
+ # Use 'ordering' attribute by default
ordering = self.get_default_ordering(view)
if ordering:
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 682a99a4..31cfa344 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -683,12 +683,12 @@ class ModelSerializer(Serializer):
# in the `read_only_fields` option
for field_name in self.opts.read_only_fields:
assert field_name not in self.base_fields.keys(), \
- "field '%s' on serializer '%s' specfied in " \
+ "field '%s' on serializer '%s' specified in " \
"`read_only_fields`, but also added " \
- "as an explict field. Remove it from `read_only_fields`." % \
+ "as an explicit field. Remove it from `read_only_fields`." % \
(field_name, self.__class__.__name__)
assert field_name in ret, \
- "Noexistant field '%s' specified in `read_only_fields` " \
+ "Non-existant field '%s' specified in `read_only_fields` " \
"on serializer '%s'." % \
(field_name, self.__class__.__name__)
ret[field_name].read_only = True
diff --git a/rest_framework/templates/rest_framework/base.html b/rest_framework/templates/rest_framework/base.html
index 9d939e73..51f9c291 100644
--- a/rest_framework/templates/rest_framework/base.html
+++ b/rest_framework/templates/rest_framework/base.html
@@ -196,7 +196,7 @@
<button class="btn btn-primary js-tooltip" name="{{ api_settings.FORM_METHOD_OVERRIDE }}" value="PUT" title="Make a PUT request on the {{ name }} resource">PUT</button>
{% endif %}
{% if raw_data_patch_form %}
- <button class="btn btn-primary js-tooltip" name="{{ api_settings.FORM_METHOD_OVERRIDE }}" value="PATCH" title="Make a PUT request on the {{ name }} resource">PATCH</button>
+ <button class="btn btn-primary js-tooltip" name="{{ api_settings.FORM_METHOD_OVERRIDE }}" value="PATCH" title="Make a PATCH request on the {{ name }} resource">PATCH</button>
{% endif %}
</div>
</fieldset>
diff --git a/rest_framework/tests/test_throttling.py b/rest_framework/tests/test_throttling.py
index 19bc691a..41bff692 100644
--- a/rest_framework/tests/test_throttling.py
+++ b/rest_framework/tests/test_throttling.py
@@ -7,7 +7,7 @@ from django.contrib.auth.models import User
from django.core.cache import cache
from rest_framework.test import APIRequestFactory
from rest_framework.views import APIView
-from rest_framework.throttling import UserRateThrottle, ScopedRateThrottle
+from rest_framework.throttling import BaseThrottle, UserRateThrottle, ScopedRateThrottle
from rest_framework.response import Response
@@ -21,6 +21,14 @@ class User3MinRateThrottle(UserRateThrottle):
scope = 'minutes'
+class NonTimeThrottle(BaseThrottle):
+ def allow_request(self, request, view):
+ if not hasattr(self.__class__, 'called'):
+ self.__class__.called = True
+ return True
+ return False
+
+
class MockView(APIView):
throttle_classes = (User3SecRateThrottle,)
@@ -35,6 +43,13 @@ class MockView_MinuteThrottling(APIView):
return Response('foo')
+class MockView_NonTimeThrottling(APIView):
+ throttle_classes = (NonTimeThrottle,)
+
+ def get(self, request):
+ return Response('foo')
+
+
class ThrottlingTests(TestCase):
def setUp(self):
"""
@@ -140,6 +155,22 @@ class ThrottlingTests(TestCase):
(80, None)
))
+ def test_non_time_throttle(self):
+ """
+ Ensure for second based throttles.
+ """
+ request = self.factory.get('/')
+
+ self.assertFalse(hasattr(MockView_NonTimeThrottling.throttle_classes[0], 'called'))
+
+ response = MockView_NonTimeThrottling.as_view()(request)
+ self.assertFalse('X-Throttle-Wait-Seconds' in response)
+
+ self.assertTrue(MockView_NonTimeThrottling.throttle_classes[0].called)
+
+ response = MockView_NonTimeThrottling.as_view()(request)
+ self.assertFalse('X-Throttle-Wait-Seconds' in response)
+
class ScopedRateThrottleTests(TestCase):
"""
diff --git a/rest_framework/throttling.py b/rest_framework/throttling.py
index f6bb1cc8..65b45593 100644
--- a/rest_framework/throttling.py
+++ b/rest_framework/throttling.py
@@ -96,6 +96,9 @@ class SimpleRateThrottle(BaseThrottle):
return True
self.key = self.get_cache_key(request, view)
+ if self.key is None:
+ return True
+
self.history = cache.get(self.key, [])
self.now = self.timer()
diff --git a/rest_framework/views.py b/rest_framework/views.py
index 37bba7f0..d51233a9 100644
--- a/rest_framework/views.py
+++ b/rest_framework/views.py
@@ -269,7 +269,7 @@ class APIView(View):
Handle any exception that occurs, by returning an appropriate response,
or re-raising the error.
"""
- if isinstance(exc, exceptions.Throttled):
+ if isinstance(exc, exceptions.Throttled) and exc.wait is not None:
# Throttle wait header
self.headers['X-Throttle-Wait-Seconds'] = '%d' % exc.wait