aboutsummaryrefslogtreecommitdiffstats
path: root/rest_framework
diff options
context:
space:
mode:
Diffstat (limited to 'rest_framework')
-rw-r--r--rest_framework/fields.py65
-rw-r--r--rest_framework/metadata.py8
-rw-r--r--rest_framework/pagination.py6
-rw-r--r--rest_framework/routers.py40
-rw-r--r--rest_framework/test.py3
5 files changed, 65 insertions, 57 deletions
diff --git a/rest_framework/fields.py b/rest_framework/fields.py
index a5348922..13ea6dde 100644
--- a/rest_framework/fields.py
+++ b/rest_framework/fields.py
@@ -556,15 +556,15 @@ class CharField(Field):
def __init__(self, **kwargs):
self.allow_blank = kwargs.pop('allow_blank', False)
self.trim_whitespace = kwargs.pop('trim_whitespace', True)
- max_length = kwargs.pop('max_length', None)
- min_length = kwargs.pop('min_length', None)
+ self.max_length = kwargs.pop('max_length', None)
+ self.min_length = kwargs.pop('min_length', None)
super(CharField, self).__init__(**kwargs)
- if max_length is not None:
- message = self.error_messages['max_length'].format(max_length=max_length)
- self.validators.append(MaxLengthValidator(max_length, message=message))
- if min_length is not None:
- message = self.error_messages['min_length'].format(min_length=min_length)
- self.validators.append(MinLengthValidator(min_length, message=message))
+ if self.max_length is not None:
+ message = self.error_messages['max_length'].format(max_length=self.max_length)
+ self.validators.append(MaxLengthValidator(self.max_length, message=message))
+ if self.min_length is not None:
+ message = self.error_messages['min_length'].format(min_length=self.min_length)
+ self.validators.append(MinLengthValidator(self.min_length, message=message))
def run_validation(self, data=empty):
# Test for the empty string here so that it does not get validated,
@@ -658,15 +658,15 @@ class IntegerField(Field):
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
def __init__(self, **kwargs):
- max_value = kwargs.pop('max_value', None)
- min_value = kwargs.pop('min_value', None)
+ self.max_value = kwargs.pop('max_value', None)
+ self.min_value = kwargs.pop('min_value', None)
super(IntegerField, self).__init__(**kwargs)
- if max_value is not None:
- message = self.error_messages['max_value'].format(max_value=max_value)
- self.validators.append(MaxValueValidator(max_value, message=message))
- if min_value is not None:
- message = self.error_messages['min_value'].format(min_value=min_value)
- self.validators.append(MinValueValidator(min_value, message=message))
+ if self.max_value is not None:
+ message = self.error_messages['max_value'].format(max_value=self.max_value)
+ self.validators.append(MaxValueValidator(self.max_value, message=message))
+ if self.min_value is not None:
+ message = self.error_messages['min_value'].format(min_value=self.min_value)
+ self.validators.append(MinValueValidator(self.min_value, message=message))
def to_internal_value(self, data):
if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH:
@@ -692,15 +692,15 @@ class FloatField(Field):
MAX_STRING_LENGTH = 1000 # Guard against malicious string inputs.
def __init__(self, **kwargs):
- max_value = kwargs.pop('max_value', None)
- min_value = kwargs.pop('min_value', None)
+ self.max_value = kwargs.pop('max_value', None)
+ self.min_value = kwargs.pop('min_value', None)
super(FloatField, self).__init__(**kwargs)
- if max_value is not None:
- message = self.error_messages['max_value'].format(max_value=max_value)
- self.validators.append(MaxValueValidator(max_value, message=message))
- if min_value is not None:
- message = self.error_messages['min_value'].format(min_value=min_value)
- self.validators.append(MinValueValidator(min_value, message=message))
+ if self.max_value is not None:
+ message = self.error_messages['max_value'].format(max_value=self.max_value)
+ self.validators.append(MaxValueValidator(self.max_value, message=message))
+ if self.min_value is not None:
+ message = self.error_messages['min_value'].format(min_value=self.min_value)
+ self.validators.append(MinValueValidator(self.min_value, message=message))
def to_internal_value(self, data):
if isinstance(data, six.text_type) and len(data) > self.MAX_STRING_LENGTH:
@@ -733,13 +733,18 @@ class DecimalField(Field):
self.max_digits = max_digits
self.decimal_places = decimal_places
self.coerce_to_string = coerce_to_string if (coerce_to_string is not None) else self.coerce_to_string
+
+ self.max_value = max_value
+ self.min_value = min_value
+
super(DecimalField, self).__init__(**kwargs)
- if max_value is not None:
- message = self.error_messages['max_value'].format(max_value=max_value)
- self.validators.append(MaxValueValidator(max_value, message=message))
- if min_value is not None:
- message = self.error_messages['min_value'].format(min_value=min_value)
- self.validators.append(MinValueValidator(min_value, message=message))
+
+ if self.max_value is not None:
+ message = self.error_messages['max_value'].format(max_value=self.max_value)
+ self.validators.append(MaxValueValidator(self.max_value, message=message))
+ if self.min_value is not None:
+ message = self.error_messages['min_value'].format(min_value=self.min_value)
+ self.validators.append(MinValueValidator(self.min_value, message=message))
def to_internal_value(self, data):
"""
diff --git a/rest_framework/metadata.py b/rest_framework/metadata.py
index 3b058fab..bf3611aa 100644
--- a/rest_framework/metadata.py
+++ b/rest_framework/metadata.py
@@ -115,7 +115,13 @@ class SimpleMetadata(BaseMetadata):
field_info['type'] = self.label_lookup[field]
field_info['required'] = getattr(field, 'required', False)
- for attr in ['read_only', 'label', 'help_text', 'min_length', 'max_length']:
+ attrs = [
+ 'read_only', 'label', 'help_text',
+ 'min_length', 'max_length',
+ 'min_value', 'max_value'
+ ]
+
+ for attr in attrs:
value = getattr(field, attr, None)
if value is not None and value != '':
field_info[attr] = force_text(value, strings_only=True)
diff --git a/rest_framework/pagination.py b/rest_framework/pagination.py
index 496500ba..80985873 100644
--- a/rest_framework/pagination.py
+++ b/rest_framework/pagination.py
@@ -259,7 +259,7 @@ class PageNumberPagination(BasePagination):
)
raise NotFound(msg)
- if paginator.count > 1:
+ if paginator.count > 1 and self.template is not None:
# The browsable API should display pagination controls.
self.display_page_controls = True
@@ -347,7 +347,7 @@ class LimitOffsetPagination(BasePagination):
self.offset = self.get_offset(request)
self.count = _get_count(queryset)
self.request = request
- if self.count > self.limit:
+ if self.count > self.limit and self.template is not None:
self.display_page_controls = True
return queryset[self.offset:self.offset + self.limit]
@@ -518,7 +518,7 @@ class CursorPagination(BasePagination):
# Display page controls in the browsable API if there is more
# than one page.
- if self.has_previous or self.has_next:
+ if (self.has_previous or self.has_next) and self.template is not None:
self.display_page_controls = True
return self.page
diff --git a/rest_framework/routers.py b/rest_framework/routers.py
index 6a4184e2..b1e39ff7 100644
--- a/rest_framework/routers.py
+++ b/rest_framework/routers.py
@@ -165,34 +165,30 @@ class SimpleRouter(BaseRouter):
else:
list_routes.append((httpmethods, methodname))
+ def _get_dynamic_routes(route, dynamic_routes):
+ ret = []
+ for httpmethods, methodname in dynamic_routes:
+ method_kwargs = getattr(viewset, methodname).kwargs
+ initkwargs = route.initkwargs.copy()
+ initkwargs.update(method_kwargs)
+ url_path = initkwargs.pop("url_path", None) or methodname
+ ret.append(Route(
+ url=replace_methodname(route.url, url_path),
+ mapping=dict((httpmethod, methodname) for httpmethod in httpmethods),
+ name=replace_methodname(route.name, url_path),
+ initkwargs=initkwargs,
+ ))
+
+ return ret
+
ret = []
for route in self.routes:
if isinstance(route, DynamicDetailRoute):
# Dynamic detail routes (@detail_route decorator)
- for httpmethods, methodname in detail_routes:
- method_kwargs = getattr(viewset, methodname).kwargs
- url_path = method_kwargs.pop("url_path", None) or methodname
- initkwargs = route.initkwargs.copy()
- initkwargs.update(method_kwargs)
- ret.append(Route(
- url=replace_methodname(route.url, url_path),
- mapping=dict((httpmethod, methodname) for httpmethod in httpmethods),
- name=replace_methodname(route.name, url_path),
- initkwargs=initkwargs,
- ))
+ ret += _get_dynamic_routes(route, detail_routes)
elif isinstance(route, DynamicListRoute):
# Dynamic list routes (@list_route decorator)
- for httpmethods, methodname in list_routes:
- method_kwargs = getattr(viewset, methodname).kwargs
- url_path = method_kwargs.pop("url_path", None) or methodname
- initkwargs = route.initkwargs.copy()
- initkwargs.update(method_kwargs)
- ret.append(Route(
- url=replace_methodname(route.url, url_path),
- mapping=dict((httpmethod, methodname) for httpmethod in httpmethods),
- name=replace_methodname(route.name, url_path),
- initkwargs=initkwargs,
- ))
+ ret += _get_dynamic_routes(route, list_routes)
else:
# Standard route
ret.append(route)
diff --git a/rest_framework/test.py b/rest_framework/test.py
index 4f4b7c20..a83d082a 100644
--- a/rest_framework/test.py
+++ b/rest_framework/test.py
@@ -209,7 +209,8 @@ class APIClient(APIRequestFactory, DjangoClient):
self.handler._force_user = None
self.handler._force_token = None
- return super(APIClient, self).logout()
+ if self.session:
+ super(APIClient, self).logout()
class APITransactionTestCase(testcases.TransactionTestCase):