diff --git a/requirements/requirements-codestyle.txt b/requirements/requirements-codestyle.txt
index 264416f5f..c61d3aa6d 100644
--- a/requirements/requirements-codestyle.txt
+++ b/requirements/requirements-codestyle.txt
@@ -1,6 +1,6 @@
# PEP8 code linting, which we run on all commits.
-flake8==2.4.0
-pep8==1.5.7
+flake8==3.0.4
+pep8==1.7.0
# Sort and lint imports
isort==4.2.5
diff --git a/requirements/requirements-packaging.txt b/requirements/requirements-packaging.txt
index f930bfa96..9a6688378 100644
--- a/requirements/requirements-packaging.txt
+++ b/requirements/requirements-packaging.txt
@@ -2,10 +2,10 @@
wheel==0.29.0
# Twine for secured PyPI uploads.
-twine==1.6.5
+twine==1.8.1
# Transifex client for managing translation resources.
-transifex-client==0.11
+transifex-client==0.12.2
# Pandoc to have a nice pypi page
pypandoc
diff --git a/rest_framework/metadata.py b/rest_framework/metadata.py
index 410acd0e2..105bcb35e 100644
--- a/rest_framework/metadata.py
+++ b/rest_framework/metadata.py
@@ -8,13 +8,18 @@ to return this information in a more standardized way.
"""
from __future__ import unicode_literals
-from collections import OrderedDict
-
from django.core.exceptions import PermissionDenied
from django.http import Http404
from django.utils.encoding import force_text
from rest_framework import exceptions, serializers
+from rest_framework.fields import (
+ BooleanField, CharField, ChoiceField, DateField, DateTimeField,
+ DecimalField, DictField, EmailField, Field, FileField, FloatField,
+ ImageField, IntegerField, ListField, MultipleChoiceField, NullBooleanField,
+ OrderedDict, RegexField, SlugField, TimeField, URLField
+)
+from rest_framework.relations import ManyRelatedField, RelatedField
from rest_framework.request import clone_request
from rest_framework.utils.field_mapping import ClassLookupDict
@@ -36,26 +41,26 @@ class SimpleMetadata(BaseMetadata):
for us to base this on.
"""
label_lookup = ClassLookupDict({
- serializers.Field: 'field',
- serializers.BooleanField: 'boolean',
- serializers.NullBooleanField: 'boolean',
- serializers.CharField: 'string',
- serializers.URLField: 'url',
- serializers.EmailField: 'email',
- serializers.RegexField: 'regex',
- serializers.SlugField: 'slug',
- serializers.IntegerField: 'integer',
- serializers.FloatField: 'float',
- serializers.DecimalField: 'decimal',
- serializers.DateField: 'date',
- serializers.DateTimeField: 'datetime',
- serializers.TimeField: 'time',
- serializers.ChoiceField: 'choice',
- serializers.MultipleChoiceField: 'multiple choice',
- serializers.FileField: 'file upload',
- serializers.ImageField: 'image upload',
- serializers.ListField: 'list',
- serializers.DictField: 'nested object',
+ Field: 'field',
+ BooleanField: 'boolean',
+ NullBooleanField: 'boolean',
+ CharField: 'string',
+ URLField: 'url',
+ EmailField: 'email',
+ RegexField: 'regex',
+ SlugField: 'slug',
+ IntegerField: 'integer',
+ FloatField: 'float',
+ DecimalField: 'decimal',
+ DateField: 'date',
+ DateTimeField: 'datetime',
+ TimeField: 'time',
+ ChoiceField: 'choice',
+ MultipleChoiceField: 'multiple choice',
+ FileField: 'file upload',
+ ImageField: 'image upload',
+ ListField: 'list',
+ DictField: 'nested object',
serializers.Serializer: 'nested object',
})
@@ -63,8 +68,10 @@ class SimpleMetadata(BaseMetadata):
metadata = OrderedDict()
metadata['name'] = view.get_view_name()
metadata['description'] = view.get_view_description()
- metadata['renders'] = [renderer.media_type for renderer in view.renderer_classes]
- metadata['parses'] = [parser.media_type for parser in view.parser_classes]
+ metadata['renders'] = [renderer.media_type for renderer in
+ view.renderer_classes]
+ metadata['parses'] = [parser.media_type for parser in
+ view.parser_classes]
if hasattr(view, 'get_serializer'):
actions = self.determine_actions(request, view)
if actions:
@@ -90,7 +97,7 @@ class SimpleMetadata(BaseMetadata):
pass
else:
# If user has appropriate permissions for the view, include
- # appropriate metadata about the fields that should be supplied.
+ # appropriate metadata about the fields that should be supplied
serializer = view.get_serializer()
actions[method] = self.get_serializer_info(serializer)
finally:
@@ -107,10 +114,9 @@ class SimpleMetadata(BaseMetadata):
# If this is a `ListSerializer` then we want to examine the
# underlying child serializer instance instead.
serializer = serializer.child
- return OrderedDict([
- (field_name, self.get_field_info(field))
- for field_name, field in serializer.fields.items()
- ])
+ return OrderedDict([(field_name, self.get_field_info(field))
+ for field_name, field in
+ serializer.fields.items()])
def get_field_info(self, field):
"""
@@ -138,14 +144,12 @@ class SimpleMetadata(BaseMetadata):
field_info['children'] = self.get_serializer_info(field)
if (not field_info.get('read_only') and
- not isinstance(field, (serializers.RelatedField, serializers.ManyRelatedField)) and
+ not isinstance(field, (RelatedField, ManyRelatedField)) and
hasattr(field, 'choices')):
- field_info['choices'] = [
- {
- 'value': choice_value,
- 'display_name': force_text(choice_name, strings_only=True)
- }
- for choice_value, choice_name in field.choices.items()
- ]
+ field_info['choices'] = [{'value': choice_value,
+ 'display_name': force_text(
+ choice_name, strings_only=True)}
+ for choice_value, choice_name in
+ field.choices.items()]
return field_info
diff --git a/rest_framework/permissions.py b/rest_framework/permissions.py
index dd2d35ccd..dfba0ecf0 100644
--- a/rest_framework/permissions.py
+++ b/rest_framework/permissions.py
@@ -7,7 +7,6 @@ from django.http import Http404
from rest_framework.compat import is_authenticated
-
SAFE_METHODS = ('GET', 'HEAD', 'OPTIONS')
diff --git a/rest_framework/renderers.py b/rest_framework/renderers.py
index 97984daf9..d24b368fd 100644
--- a/rest_framework/renderers.py
+++ b/rest_framework/renderers.py
@@ -9,16 +9,13 @@ REST framework also provides an HTML renderer that renders the browsable API.
from __future__ import unicode_literals
import json
-from collections import OrderedDict
from django import forms
from django.conf import settings
-from django.core.exceptions import ImproperlyConfigured
from django.core.paginator import Page
from django.http.multipartparser import parse_header
from django.template import Template, loader
from django.test.client import encode_multipart
-from django.utils import six
from rest_framework import VERSION, exceptions, serializers, status
from rest_framework.compat import (
@@ -26,6 +23,14 @@ from rest_framework.compat import (
template_render
)
from rest_framework.exceptions import ParseError
+from rest_framework.fields import (
+ BooleanField, ChoiceField, DateField, DateTimeField, EmailField, Field,
+ FileField, FilePathField, FloatField, HiddenField, IntegerField,
+ MultipleChoiceField, OrderedDict, TimeField, URLField, six
+)
+from rest_framework.relations import (
+ ImproperlyConfigured, ManyRelatedField, RelatedField
+)
from rest_framework.request import is_form_media_type, override_method
from rest_framework.settings import api_settings
from rest_framework.utils import encoders
@@ -48,7 +53,8 @@ class BaseRenderer(object):
render_style = 'text'
def render(self, data, accepted_media_type=None, renderer_context=None):
- raise NotImplementedError('Renderer class requires .render() to be implemented')
+ raise NotImplementedError(
+ 'Renderer class requires .render() to be implemented')
class JSONRenderer(BaseRenderer):
@@ -64,7 +70,7 @@ class JSONRenderer(BaseRenderer):
# We don't set a charset because JSON is a binary encoding,
# that can be encoded as utf-8, utf-16 or utf-32.
# See: http://www.ietf.org/rfc/rfc4627.txt
- # Also: http://lucumr.pocoo.org/2013/7/19/application-mimetypes-and-encodings/
+ # http://lucumr.pocoo.org/2013/7/19/application-mimetypes-and-encodings/
charset = None
def get_indent(self, accepted_media_type, renderer_context):
@@ -72,7 +78,8 @@ class JSONRenderer(BaseRenderer):
# If the media type looks like 'application/json; indent=4',
# then pretty print the result.
# Note that we coerce `indent=0` into `indent=None`.
- base_media_type, params = parse_header(accepted_media_type.encode('ascii'))
+ base_media_type, params = parse_header(
+ accepted_media_type.encode('ascii'))
try:
return zero_as_none(max(min(int(params['indent']), 8), 0))
except (KeyError, ValueError, TypeError):
@@ -192,7 +199,8 @@ class TemplateHTMLRenderer(BaseRenderer):
elif hasattr(view, 'template_name'):
return [view.template_name]
raise ImproperlyConfigured(
- 'Returned a template response with no `template_name` attribute set on either the view or response'
+ 'Returned a template response with no `template_name` attribute '
+ 'set on either the view or response'
)
def get_exception_template(self, response):
@@ -260,56 +268,58 @@ class HTMLFormRenderer(BaseRenderer):
base_template = 'form.html'
default_style = ClassLookupDict({
- serializers.Field: {
+ Field: {
'base_template': 'input.html',
'input_type': 'text'
},
- serializers.EmailField: {
+ EmailField: {
'base_template': 'input.html',
'input_type': 'email'
},
- serializers.URLField: {
+ URLField: {
'base_template': 'input.html',
'input_type': 'url'
},
- serializers.IntegerField: {
+ IntegerField: {
'base_template': 'input.html',
'input_type': 'number'
},
- serializers.FloatField: {
+ FloatField: {
'base_template': 'input.html',
'input_type': 'number'
},
- serializers.DateTimeField: {
+ DateTimeField: {
'base_template': 'input.html',
'input_type': 'datetime-local'
},
- serializers.DateField: {
+ DateField: {
'base_template': 'input.html',
'input_type': 'date'
},
- serializers.TimeField: {
+ TimeField: {
'base_template': 'input.html',
'input_type': 'time'
},
- serializers.FileField: {
+ FileField: {
'base_template': 'input.html',
'input_type': 'file'
},
- serializers.BooleanField: {
+ BooleanField: {
'base_template': 'checkbox.html'
},
- serializers.ChoiceField: {
+ ChoiceField: {
'base_template': 'select.html', # Also valid: 'radio.html'
},
- serializers.MultipleChoiceField: {
- 'base_template': 'select_multiple.html', # Also valid: 'checkbox_multiple.html'
+ MultipleChoiceField: {
+ 'base_template': 'select_multiple.html',
+ # Also valid: 'checkbox_multiple.html'
},
- serializers.RelatedField: {
+ RelatedField: {
'base_template': 'select.html', # Also valid: 'radio.html'
},
- serializers.ManyRelatedField: {
- 'base_template': 'select_multiple.html', # Also valid: 'checkbox_multiple.html'
+ ManyRelatedField: {
+ 'base_template': 'select_multiple.html',
+ # Also valid: 'checkbox_multiple.html'
},
serializers.Serializer: {
'base_template': 'fieldset.html'
@@ -317,31 +327,34 @@ class HTMLFormRenderer(BaseRenderer):
serializers.ListSerializer: {
'base_template': 'list_fieldset.html'
},
- serializers.FilePathField: {
+ FilePathField: {
'base_template': 'select.html',
},
})
def render_field(self, field, parent_style):
- if isinstance(field._field, serializers.HiddenField):
+ if isinstance(field._field, HiddenField):
return ''
style = dict(self.default_style[field])
style.update(field.style)
if 'template_pack' not in style:
- style['template_pack'] = parent_style.get('template_pack', self.template_pack)
+ style['template_pack'] = parent_style.get('template_pack',
+ self.template_pack)
style['renderer'] = self
# Get a clone of the field with text-only value representation.
field = field.as_form_field()
- if style.get('input_type') == 'datetime-local' and isinstance(field.value, six.text_type):
+ if style.get('input_type') == 'datetime-local' and isinstance(
+ field.value, six.text_type):
field.value = field.value.rstrip('Z')
if 'template' in style:
template_name = style['template']
else:
- template_name = style['template_pack'].strip('/') + '/' + style['base_template']
+ template_name = style['template_pack'].strip('/') + '/' + style[
+ 'base_template']
template = loader.get_template(template_name)
context = {'field': field, 'style': style}
@@ -388,7 +401,8 @@ class BrowsableAPIRenderer(BaseRenderer):
renderers = [renderer for renderer in view.renderer_classes
if not issubclass(renderer, BrowsableAPIRenderer)]
non_template_renderers = [renderer for renderer in renderers
- if not hasattr(renderer, 'get_template_names')]
+ if
+ not hasattr(renderer, 'get_template_names')]
if not renderers:
return None
@@ -410,7 +424,8 @@ class BrowsableAPIRenderer(BaseRenderer):
render_style = getattr(renderer, 'render_style', 'text')
assert render_style in ['text', 'binary'], 'Expected .render_style ' \
- '"text" or "binary", but got "%s"' % render_style
+ '"text" or "binary", but ' \
+ 'got "%s"' % render_style
if render_style == 'binary':
return '[%d bytes of binary content]' % len(content)
@@ -431,7 +446,8 @@ class BrowsableAPIRenderer(BaseRenderer):
return False # Doesn't have permissions
return True
- def _get_serializer(self, serializer_class, view_instance, request, *args, **kwargs):
+ def _get_serializer(self, serializer_class, view_instance, request, *args,
+ **kwargs):
kwargs['context'] = {
'request': request,
'format': self.format,
@@ -478,10 +494,10 @@ class BrowsableAPIRenderer(BaseRenderer):
has_serializer = getattr(view, 'get_serializer', None)
has_serializer_class = getattr(view, 'serializer_class', None)
- if (
- (not has_serializer and not has_serializer_class) or
- not any(is_form_media_type(parser.media_type) for parser in view.parser_classes)
- ):
+ if ((not has_serializer and not has_serializer_class) or
+ not any(
+ is_form_media_type(parser.media_type) for parser in
+ view.parser_classes)):
return
if existing_serializer is not None:
@@ -492,16 +508,21 @@ class BrowsableAPIRenderer(BaseRenderer):
if has_serializer:
if method in ('PUT', 'PATCH'):
- serializer = view.get_serializer(instance=instance, **kwargs)
+ serializer = view.get_serializer(instance=instance,
+ **kwargs)
else:
serializer = view.get_serializer(**kwargs)
else:
# at this point we must have a serializer_class
if method in ('PUT', 'PATCH'):
- serializer = self._get_serializer(view.serializer_class, view,
- request, instance=instance, **kwargs)
+ serializer = self._get_serializer(view.serializer_class,
+ view,
+ request,
+ instance=instance,
+ **kwargs)
else:
- serializer = self._get_serializer(view.serializer_class, view,
+ serializer = self._get_serializer(view.serializer_class,
+ view,
request, **kwargs)
return self.render_form_for_serializer(serializer)
@@ -569,7 +590,8 @@ class BrowsableAPIRenderer(BaseRenderer):
label='Media type',
choices=choices,
initial=initial,
- widget=forms.Select(attrs={'data-override': 'content-type'})
+ widget=forms.Select(
+ attrs={'data-override': 'content-type'})
)
_content = forms.CharField(
label='Content',
@@ -583,7 +605,8 @@ class BrowsableAPIRenderer(BaseRenderer):
return view.get_view_name()
def get_description(self, view, status_code):
- if status_code in (status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN):
+ if status_code in (
+ status.HTTP_401_UNAUTHORIZED, status.HTTP_403_FORBIDDEN):
return ''
return view.get_view_description(html=True)
@@ -591,7 +614,8 @@ class BrowsableAPIRenderer(BaseRenderer):
return get_breadcrumbs(request.path, request)
def get_filter_form(self, data, view, request):
- if not hasattr(view, 'get_queryset') or not hasattr(view, 'filter_backends'):
+ if not hasattr(view, 'get_queryset') or not hasattr(view,
+ 'filter_backends'):
return
# Infer if this is a list view or not.
@@ -631,9 +655,11 @@ class BrowsableAPIRenderer(BaseRenderer):
renderer = self.get_default_renderer(view)
- raw_data_post_form = self.get_raw_data_form(data, view, 'POST', request)
+ raw_data_post_form = self.get_raw_data_form(data, view, 'POST',
+ request)
raw_data_put_form = self.get_raw_data_form(data, view, 'PUT', request)
- raw_data_patch_form = self.get_raw_data_form(data, view, 'PATCH', request)
+ raw_data_patch_form = self.get_raw_data_form(data, view, 'PATCH',
+ request)
raw_data_put_or_patch_form = raw_data_put_form or raw_data_patch_form
response_headers = OrderedDict(sorted(response.items()))
@@ -644,19 +670,22 @@ class BrowsableAPIRenderer(BaseRenderer):
renderer_content_type += ' ;%s' % renderer.charset
response_headers['Content-Type'] = renderer_content_type
- if getattr(view, 'paginator', None) and view.paginator.display_page_controls:
+ if getattr(view, 'paginator',
+ None) and view.paginator.display_page_controls:
paginator = view.paginator
else:
paginator = None
csrf_cookie_name = settings.CSRF_COOKIE_NAME
- csrf_header_name = getattr(settings, 'CSRF_HEADER_NAME', 'HTTP_X_CSRFToken') # Fallback for Django 1.8
+ csrf_header_name = getattr(settings, 'CSRF_HEADER_NAME',
+ 'HTTP_X_CSRFToken') # Fallback Django 1.8
if csrf_header_name.startswith('HTTP_'):
csrf_header_name = csrf_header_name[5:]
csrf_header_name = csrf_header_name.replace('_', '-')
context = {
- 'content': self.get_content(renderer, data, accepted_media_type, renderer_context),
+ 'content': self.get_content(renderer, data, accepted_media_type,
+ renderer_context),
'view': view,
'request': request,
'response': response,
@@ -667,13 +696,18 @@ class BrowsableAPIRenderer(BaseRenderer):
'paginator': paginator,
'breadcrumblist': self.get_breadcrumbs(request),
'allowed_methods': view.allowed_methods,
- 'available_formats': [renderer_cls.format for renderer_cls in view.renderer_classes],
+ 'available_formats': [renderer_cls.format for renderer_cls in
+ view.renderer_classes],
'response_headers': response_headers,
- 'put_form': self.get_rendered_html_form(data, view, 'PUT', request),
- 'post_form': self.get_rendered_html_form(data, view, 'POST', request),
- 'delete_form': self.get_rendered_html_form(data, view, 'DELETE', request),
- 'options_form': self.get_rendered_html_form(data, view, 'OPTIONS', request),
+ 'put_form': self.get_rendered_html_form(data, view, 'PUT',
+ request),
+ 'post_form': self.get_rendered_html_form(data, view, 'POST',
+ request),
+ 'delete_form': self.get_rendered_html_form(data, view, 'DELETE',
+ request),
+ 'options_form': self.get_rendered_html_form(data, view, 'OPTIONS',
+ request),
'filter_form': self.get_filter_form(data, view, request),
@@ -699,7 +733,8 @@ class BrowsableAPIRenderer(BaseRenderer):
template = loader.get_template(self.template)
context = self.get_context(data, accepted_media_type, renderer_context)
- ret = template_render(template, context, request=renderer_context['request'])
+ ret = template_render(template, context,
+ request=renderer_context['request'])
# Munge DELETE Response code to allow us to return content
# (Do this *after* we've rendered the template so that we include
@@ -726,8 +761,11 @@ class AdminRenderer(BrowsableAPIRenderer):
if response.status_code == status.HTTP_400_BAD_REQUEST:
# Errors still need to display the list or detail information.
# The only way we can get at that is to simulate a GET request.
- self.error_form = self.get_rendered_html_form(data, view, request.method, request)
- self.error_title = {'POST': 'Create', 'PUT': 'Edit'}.get(request.method, 'Errors')
+ self.error_form = self.get_rendered_html_form(data, view,
+ request.method,
+ request)
+ self.error_title = {'POST': 'Create', 'PUT': 'Edit'}.get(
+ request.method, 'Errors')
with override_method(view, request, 'GET') as request:
response = view.get(request, *view.args, **view.kwargs)
@@ -735,10 +773,12 @@ class AdminRenderer(BrowsableAPIRenderer):
template = loader.get_template(self.template)
context = self.get_context(data, accepted_media_type, renderer_context)
- ret = template_render(template, context, request=renderer_context['request'])
+ ret = template_render(template, context,
+ request=renderer_context['request'])
# Creation and deletion should use redirects in the admin style.
- if (response.status_code == status.HTTP_201_CREATED) and ('Location' in response):
+ if (response.status_code == status.HTTP_201_CREATED) \
+ and ('Location' in response):
response.status_code = status.HTTP_303_SEE_OTHER
response['Location'] = request.build_absolute_uri()
ret = ''
@@ -818,7 +858,8 @@ class CoreJSONRenderer(BaseRenderer):
format = 'corejson'
def __init__(self):
- assert coreapi, 'Using CoreJSONRenderer, but `coreapi` is not installed.'
+ assert coreapi, 'Using CoreJSONRenderer, but `coreapi` is not ' \
+ 'installed.'
def render(self, data, media_type=None, renderer_context=None):
indent = bool(renderer_context.get('indent', 0))
diff --git a/rest_framework/response.py b/rest_framework/response.py
index cb0f290ce..a777192dd 100644
--- a/rest_framework/response.py
+++ b/rest_framework/response.py
@@ -10,7 +10,7 @@ from django.template.response import SimpleTemplateResponse
from django.utils import six
from django.utils.six.moves.http_client import responses
-from rest_framework.serializers import Serializer
+from rest_framework import serializers
class Response(SimpleTemplateResponse):
@@ -31,7 +31,7 @@ class Response(SimpleTemplateResponse):
"""
super(Response, self).__init__(None, status=status)
- if isinstance(data, Serializer):
+ if isinstance(data, serializers.Serializer):
msg = (
'You passed a Serializer instance as data, but '
'probably meant to pass serialized `.data` or '
@@ -98,8 +98,8 @@ class Response(SimpleTemplateResponse):
"""
state = super(Response, self).__getstate__()
for key in (
- 'accepted_renderer', 'renderer_context', 'resolver_match',
- 'client', 'request', 'json', 'wsgi_request'
+ 'accepted_renderer', 'renderer_context', 'resolver_match',
+ 'client', 'request', 'json', 'wsgi_request'
):
if key in state:
del state[key]
diff --git a/rest_framework/schemas.py b/rest_framework/schemas.py
index 9b9984699..0df3c576d 100644
--- a/rest_framework/schemas.py
+++ b/rest_framework/schemas.py
@@ -4,13 +4,17 @@ from importlib import import_module
from django.conf import settings
from django.contrib.admindocs.views import simplify_regex
-from django.utils import six
from django.utils.encoding import force_text, smart_text
from rest_framework import exceptions, renderers, serializers
from rest_framework.compat import (
RegexURLPattern, RegexURLResolver, coreapi, uritemplate, urlparse
)
+from rest_framework.fields import (
+ BooleanField, DecimalField, Field, FileField, FloatField, HiddenField,
+ IntegerField, MultipleChoiceField, six
+)
+from rest_framework.relations import ManyRelatedField
from rest_framework.request import clone_request
from rest_framework.response import Response
from rest_framework.settings import api_settings
@@ -19,18 +23,17 @@ from rest_framework.utils.field_mapping import ClassLookupDict
from rest_framework.utils.model_meta import _get_pk
from rest_framework.views import APIView
-
header_regex = re.compile('^[a-zA-Z][0-9A-Za-z_]*:')
types_lookup = ClassLookupDict({
- serializers.Field: 'string',
- serializers.IntegerField: 'integer',
- serializers.FloatField: 'number',
- serializers.DecimalField: 'number',
- serializers.BooleanField: 'boolean',
- serializers.FileField: 'file',
- serializers.MultipleChoiceField: 'array',
- serializers.ManyRelatedField: 'array',
+ Field: 'string',
+ IntegerField: 'integer',
+ FloatField: 'number',
+ DecimalField: 'number',
+ BooleanField: 'boolean',
+ FileField: 'file',
+ MultipleChoiceField: 'array',
+ ManyRelatedField: 'array',
serializers.Serializer: 'object',
serializers.ListSerializer: 'array'
})
@@ -115,6 +118,7 @@ class EndpointInspector(object):
"""
A class to determine the available API endpoints that a project exposes.
"""
+
def __init__(self, patterns=None, urlconf=None):
if patterns is None:
if urlconf is None:
@@ -187,10 +191,8 @@ class EndpointInspector(object):
if hasattr(callback, 'actions'):
return [method.upper() for method in callback.actions.keys()]
- return [
- method for method in
- callback.cls().allowed_methods if method not in ('OPTIONS', 'HEAD')
- ]
+ return [method for method in callback.cls().allowed_methods
+ if method not in ('OPTIONS', 'HEAD')]
class SchemaGenerator(object):
@@ -204,8 +206,9 @@ class SchemaGenerator(object):
}
endpoint_inspector_cls = EndpointInspector
- # Map the method names we use for viewset actions onto external schema names.
- # These give us names that are more suitable for the external representation.
+ # Map the method names we use for viewset actions onto external schema
+ # names. These give us names that are more suitable for the external
+ # representation.
# Set by 'SCHEMA_COERCE_METHOD_NAMES'.
coerce_method_names = None
@@ -234,7 +237,8 @@ class SchemaGenerator(object):
Generate a `coreapi.Document` representing the API schema.
"""
if self.endpoints is None:
- inspector = self.endpoint_inspector_cls(self.patterns, self.urlconf)
+ inspector = self.endpoint_inspector_cls(self.patterns,
+ self.urlconf)
self.endpoints = inspector.get_api_endpoints()
links = self.get_links(request)
@@ -369,7 +373,8 @@ class SchemaGenerator(object):
fields += self.get_pagination_fields(path, method, view)
fields += self.get_filter_fields(path, method, view)
- if fields and any([field.location in ('form', 'body') for field in fields]):
+ if fields and any(
+ [field.location in ('form', 'body') for field in fields]):
encoding = self.get_encoding(path, method, view)
else:
encoding = None
@@ -449,7 +454,8 @@ class SchemaGenerator(object):
fields = []
for variable in uritemplate.variables(path):
- field = coreapi.Field(name=variable, location='path', required=True)
+ field = coreapi.Field(name=variable, location='path',
+ required=True)
fields.append(field)
return fields
@@ -482,11 +488,12 @@ class SchemaGenerator(object):
fields = []
for field in serializer.fields.values():
- if field.read_only or isinstance(field, serializers.HiddenField):
+ if field.read_only or isinstance(field, HiddenField):
continue
required = field.required and method != 'PATCH'
- description = force_text(field.help_text) if field.help_text else ''
+ description = force_text(
+ field.help_text) if field.help_text else ''
field = coreapi.Field(
name=field.field_name,
location='form',
@@ -528,27 +535,30 @@ class SchemaGenerator(object):
the schema document.
/users/ ("users", "list"), ("users", "create")
- /users/{pk}/ ("users", "read"), ("users", "update"), ("users", "delete")
- /users/enabled/ ("users", "enabled") # custom viewset list action
- /users/{pk}/star/ ("users", "star") # custom viewset detail action
- /users/{pk}/groups/ ("users", "groups", "list"), ("users", "groups", "create")
- /users/{pk}/groups/{pk}/ ("users", "groups", "read"), ("users", "groups", "update"), ("users", "groups", "delete")
+ /users/{pk}/ ("users", "read"), ("users", "update"),
+ ("users", "delete")
+ /users/enabled/ ("users", "enabled") # custom viewset list
+ /users/{pk}/star/ ("users", "star") # custom viewset detail
+ /users/{pk}/groups/ ("users", "groups", "list"),
+ ("users", "groups", "create")
+ /users/{pk}/groups/{pk}/ ("users", "groups", "read"),
+ ("users", "groups", "update"),
+ ("users", "groups", "delete")
"""
if hasattr(view, 'action'):
# Viewsets have explicitly named actions.
action = view.action
else:
- # Views have no associated action, so we determine one from the method.
+ # Views have no associated action, so we determine one from the
+ # method.
if is_list_view(subpath, method, view):
action = 'list'
else:
action = self.default_mapping[method.lower()]
- named_path_components = [
- component for component
- in subpath.strip('/').split('/')
- if '{' not in component
- ]
+ named_path_components = [component for component
+ in subpath.strip('/').split('/')
+ if '{' not in component]
if is_custom_action(action):
# Custom action, eg "/users/{pk}/activate/", "/users/active/"
@@ -573,8 +583,10 @@ def get_schema_view(title=None, url=None, renderer_classes=None):
"""
generator = SchemaGenerator(title=title, url=url)
if renderer_classes is None:
- if renderers.BrowsableAPIRenderer in api_settings.DEFAULT_RENDERER_CLASSES:
- rclasses = [renderers.CoreJSONRenderer, renderers.BrowsableAPIRenderer]
+ if renderers.BrowsableAPIRenderer in \
+ api_settings.DEFAULT_RENDERER_CLASSES:
+ rclasses = [renderers.CoreJSONRenderer,
+ renderers.BrowsableAPIRenderer]
else:
rclasses = [renderers.CoreJSONRenderer]
else:
diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py
index 39987cd07..d6c6675f7 100644
--- a/rest_framework/serializers.py
+++ b/rest_framework/serializers.py
@@ -12,7 +12,9 @@ response content is handled by parsers and renderers.
"""
from __future__ import unicode_literals
+import inspect
import traceback
+from copy import deepcopy
from django.db import models
from django.db.models import DurationField as ModelDurationField
@@ -23,6 +25,20 @@ from django.utils.translation import ugettext_lazy as _
from rest_framework.compat import JSONField as ModelJSONField
from rest_framework.compat import postgres_fields, set_many, unicode_to_repr
+from rest_framework.fields import (
+ BooleanField, CharField, ChoiceField, CreateOnlyDefault, DateField,
+ DateTimeField, DecimalField, DictField, DjangoValidationError,
+ DurationField, EmailField, ErrorDetail, Field, FileField, FilePathField,
+ FloatField, HiddenField, ImageField, IntegerField, IPAddressField,
+ JSONField, ListField, ModelField, NullBooleanField, OrderedDict,
+ ReadOnlyField, SkipField, SlugField, TimeField, URLField, UUIDField,
+ ValidationError, api_settings, empty, get_error_detail, html,
+ representation, set_value, six, timezone
+)
+from rest_framework.relations import (
+ HyperlinkedIdentityField, HyperlinkedRelatedField, ImproperlyConfigured,
+ PKOnlyObject, PrimaryKeyRelatedField, SlugRelatedField
+)
from rest_framework.utils import model_meta
from rest_framework.utils.field_mapping import (
ClassLookupDict, get_field_kwargs, get_nested_relation_kwargs,
@@ -36,16 +52,6 @@ from rest_framework.validators import (
UniqueTogetherValidator
)
-# Note: We do the following so that users of the framework can use this style:
-#
-# example_field = serializers.CharField(...)
-#
-# This helps keep the separation between model fields, form fields, and
-# serializer fields more explicit.
-
-from rest_framework.fields import * # NOQA # isort:skip
-from rest_framework.relations import * # NOQA # isort:skip
-
# We assume that 'validators' are intended for the child serializer,
# rather than the parent serializer.
LIST_SERIALIZER_KWARGS = (
@@ -125,12 +131,11 @@ class BaseSerializer(Field):
}
if allow_empty is not None:
list_kwargs['allow_empty'] = allow_empty
- list_kwargs.update({
- key: value for key, value in kwargs.items()
- if key in LIST_SERIALIZER_KWARGS
- })
+ list_kwargs.update({key: value for key, value in kwargs.items()
+ if key in LIST_SERIALIZER_KWARGS})
meta = getattr(cls, 'Meta', None)
- list_serializer_class = getattr(meta, 'list_serializer_class', ListSerializer)
+ list_serializer_class = getattr(meta, 'list_serializer_class',
+ ListSerializer)
return list_serializer_class(*args, **list_kwargs)
def to_internal_value(self, data):
@@ -164,17 +169,17 @@ class BaseSerializer(Field):
# Guard against incorrect use of `serializer.save(commit=False)`
assert 'commit' not in kwargs, (
"'commit' is not a valid keyword argument to the 'save()' method. "
- "If you need to access data before committing to the database then "
- "inspect 'serializer.validated_data' instead. "
- "You can also pass additional keyword arguments to 'save()' if you "
- "need to set extra attributes on the saved model instance. "
+ "If you need to access data before committing to the database then"
+ " inspect 'serializer.validated_data' instead. "
+ "You can also pass additional keyword arguments to 'save()' if you"
+ " need to set extra attributes on the saved model instance. "
"For example: 'serializer.save(owner=request.user)'.'"
)
assert not hasattr(self, '_data'), (
"You cannot call `.save()` after accessing `serializer.data`."
- "If you need to access data before committing to the database then "
- "inspect 'serializer.validated_data' instead. "
+ "If you need to access data before committing to the database then"
+ " inspect 'serializer.validated_data' instead. "
)
validated_data = dict(
@@ -224,7 +229,8 @@ class BaseSerializer(Field):
@property
def data(self):
- if hasattr(self, 'initial_data') and not hasattr(self, '_validated_data'):
+ if hasattr(self, 'initial_data') and not hasattr(self,
+ '_validated_data'):
msg = (
'When a serializer is passed a `data` keyword argument you '
'must call `.is_valid()` before attempting to access the '
@@ -235,9 +241,12 @@ class BaseSerializer(Field):
raise AssertionError(msg)
if not hasattr(self, '_data'):
- if self.instance is not None and not getattr(self, '_errors', None):
+ if self.instance is not None and not getattr(self, '_errors',
+ None):
self._data = self.to_representation(self.instance)
- elif hasattr(self, '_validated_data') and not getattr(self, '_errors', None):
+ elif hasattr(self, '_validated_data') and not getattr(self,
+ '_errors',
+ None):
self._data = self.to_representation(self.validated_data)
else:
self._data = self.get_initial()
@@ -253,7 +262,8 @@ class BaseSerializer(Field):
@property
def validated_data(self):
if not hasattr(self, '_validated_data'):
- msg = 'You must call `.is_valid()` before accessing `.validated_data`.'
+ msg = 'You must call `.is_valid()` before accessing ' \
+ '`.validated_data`.'
raise AssertionError(msg)
return self._validated_data
@@ -277,9 +287,9 @@ class SerializerMetaclass(type):
if isinstance(obj, Field)]
fields.sort(key=lambda x: x[1]._creation_counter)
- # If this class is subclassing another Serializer, add that Serializer's
- # fields. Note that we loop over the bases in *reverse*. This is necessary
- # in order to maintain the correct order of fields.
+ # If this class is subclassing another Serializer, add that
+ # Serializer's fields. Note that we loop over the bases in *reverse*.
+ # This is necessary in order to maintain the correct order of fields.
for base in reversed(bases):
if hasattr(base, '_declared_fields'):
fields = list(base._declared_fields.items()) + fields
@@ -302,10 +312,8 @@ def as_serializer_error(exc):
if isinstance(detail, dict):
# If errors may be a dict we use the standard {key: list of values}.
# Here we ensure that all the values are *lists* of errors.
- return {
- key: value if isinstance(value, (list, dict)) else [value]
- for key, value in detail.items()
- }
+ return {key: value if isinstance(value, (list, dict)) else [value]
+ for key, value in detail.items()}
elif isinstance(detail, list):
# Errors raised as a list are non-field errors.
return {
@@ -320,7 +328,8 @@ def as_serializer_error(exc):
@six.add_metaclass(SerializerMetaclass)
class Serializer(BaseSerializer):
default_error_messages = {
- 'invalid': _('Invalid data. Expected a dictionary, but got {datatype}.')
+ 'invalid': _(
+ 'Invalid data. Expected a dictionary, but got {datatype}.')
}
@property
@@ -339,17 +348,13 @@ class Serializer(BaseSerializer):
@cached_property
def _writable_fields(self):
- return [
- field for field in self.fields.values()
- if (not field.read_only) or (field.default is not empty)
- ]
+ return [field for field in self.fields.values()
+ if (not field.read_only) or (field.default is not empty)]
@cached_property
def _readable_fields(self):
- return [
- field for field in self.fields.values()
- if not field.write_only
- ]
+ return [field for field in self.fields.values()
+ if not field.write_only]
def get_fields(self):
"""
@@ -358,7 +363,7 @@ class Serializer(BaseSerializer):
# Every new serializer is created with a clone of the field instances.
# This allows users to dynamically modify the fields on a serializer
# instance without affecting every other serializer class.
- return copy.deepcopy(self._declared_fields)
+ return deepcopy(self._declared_fields)
def get_validators(self):
"""
@@ -371,24 +376,22 @@ class Serializer(BaseSerializer):
def get_initial(self):
if hasattr(self, 'initial_data'):
- return OrderedDict([
- (field_name, field.get_value(self.initial_data))
- for field_name, field in self.fields.items()
- if (field.get_value(self.initial_data) is not empty) and
- not field.read_only
- ])
+ return OrderedDict([(field_name,
+ field.get_value(self.initial_data))
+ for field_name, field in self.fields.items()
+ if (field.get_value(self.initial_data)
+ is not empty) and not field.read_only])
- return OrderedDict([
- (field.field_name, field.get_initial())
- for field in self.fields.values()
- if not field.read_only
- ])
+ return OrderedDict([(field.field_name, field.get_initial())
+ for field in self.fields.values()
+ if not field.read_only])
def get_value(self, dictionary):
# We override the default field access in order to support
# nested HTML forms.
if html.is_html_input(dictionary):
- return html.parse_html_dict(dictionary, prefix=self.field_name) or empty
+ return html.parse_html_dict(dictionary,
+ prefix=self.field_name) or empty
return dictionary.get(self.field_name, empty)
def run_validation(self, data=empty):
@@ -405,7 +408,8 @@ class Serializer(BaseSerializer):
try:
self.run_validators(value)
value = self.validate(value)
- assert value is not None, '.validate() should return the validated data'
+ assert value is not None, '.validate() should return the ' \
+ 'validated data'
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
@@ -428,7 +432,8 @@ class Serializer(BaseSerializer):
fields = self._writable_fields
for field in fields:
- validate_method = getattr(self, 'validate_' + field.field_name, None)
+ validate_method = getattr(self, 'validate_' + field.field_name,
+ None)
primitive_value = field.get_value(data)
try:
validated_value = field.run_validation(primitive_value)
@@ -466,7 +471,8 @@ class Serializer(BaseSerializer):
#
# For related fields with `use_pk_only_optimization` we need to
# resolve the pk value.
- check_for_none = attribute.pk if isinstance(attribute, PKOnlyObject) else attribute
+ check_for_none = attribute.pk if \
+ isinstance(attribute, PKOnlyObject) else attribute
if check_for_none is None:
ret[field.field_name] = None
else:
@@ -523,15 +529,17 @@ class ListSerializer(BaseSerializer):
many = True
default_error_messages = {
- 'not_a_list': _('Expected a list of items but got type "{input_type}".'),
+ 'not_a_list': _(
+ 'Expected a list of items but got type "{input_type}".'),
'empty': _('This list may not be empty.')
}
def __init__(self, *args, **kwargs):
- self.child = kwargs.pop('child', copy.deepcopy(self.child))
+ self.child = kwargs.pop('child', deepcopy(self.child))
self.allow_empty = kwargs.pop('allow_empty', True)
assert self.child is not None, '`child` is a required argument.'
- assert not inspect.isclass(self.child), '`child` has not been instantiated.'
+ assert not inspect.isclass(
+ self.child), '`child` has not been instantiated.'
super(ListSerializer, self).__init__(*args, **kwargs)
self.child.bind(field_name='', parent=self)
@@ -564,7 +572,8 @@ class ListSerializer(BaseSerializer):
try:
self.run_validators(value)
value = self.validate(value)
- assert value is not None, '.validate() should return the validated data'
+ assert value is not None, '.validate() should return the ' \
+ 'validated data'
except (ValidationError, DjangoValidationError) as exc:
raise ValidationError(detail=as_serializer_error(exc))
@@ -616,9 +625,7 @@ class ListSerializer(BaseSerializer):
# so, first get a queryset from the Manager if needed
iterable = data.all() if isinstance(data, models.Manager) else data
- return [
- self.child.to_representation(item) for item in iterable
- ]
+ return [self.child.to_representation(item) for item in iterable]
def validate(self, attrs):
return attrs
@@ -633,9 +640,7 @@ class ListSerializer(BaseSerializer):
)
def create(self, validated_data):
- return [
- self.child.create(attrs) for attrs in validated_data
- ]
+ return [self.child.create(attrs) for attrs in validated_data]
def save(self, **kwargs):
"""
@@ -644,17 +649,15 @@ class ListSerializer(BaseSerializer):
# Guard against incorrect use of `serializer.save(commit=False)`
assert 'commit' not in kwargs, (
"'commit' is not a valid keyword argument to the 'save()' method. "
- "If you need to access data before committing to the database then "
- "inspect 'serializer.validated_data' instead. "
- "You can also pass additional keyword arguments to 'save()' if you "
- "need to set extra attributes on the saved model instance. "
+ "If you need to access data before committing to the database then"
+ " inspect 'serializer.validated_data' instead. "
+ "You can also pass additional keyword arguments to 'save()' if you"
+ " need to set extra attributes on the saved model instance. "
"For example: 'serializer.save(owner=request.user)'.'"
)
- validated_data = [
- dict(list(attrs.items()) + list(kwargs.items()))
- for attrs in self.validated_data
- ]
+ validated_data = [dict(list(attrs.items()) + list(kwargs.items()))
+ for attrs in self.validated_data]
if self.instance is not None:
self.instance = self.update(self.instance, validated_data)
@@ -769,8 +772,8 @@ def raise_errors_on_nested_writes(method_name, serializer, validated_data):
isinstance(validated_data[key], (list, dict))
for key, field in serializer.fields.items()
), (
- 'The `.{method_name}()` method does not support writable dotted-source '
- 'fields by default.\nWrite an explicit `.{method_name}()` method for '
+ 'The `.{method_name}()` method does not support writable dotted-source'
+ ' fields by default.\nWrite an explicit `.{method_name}()` method for '
'serializer `{module}.{class_name}`, or set `read_only=True` on '
'dotted-source serializer fields.'.format(
method_name=method_name,
@@ -944,7 +947,7 @@ class ModelSerializer(Serializer):
'Cannot use ModelSerializer with Abstract Models.'
)
- declared_fields = copy.deepcopy(self._declared_fields)
+ declared_fields = deepcopy(self._declared_fields)
model = getattr(self.Meta, 'model')
depth = getattr(self.Meta, 'depth', 0)
@@ -1003,7 +1006,8 @@ class ModelSerializer(Serializer):
fields = getattr(self.Meta, 'fields', None)
exclude = getattr(self.Meta, 'exclude', None)
- if fields and fields != ALL_FIELDS and not isinstance(fields, (list, tuple)):
+ if fields and fields != ALL_FIELDS and not isinstance(fields,
+ (list, tuple)):
raise TypeError(
'The `fields` option must be a list or tuple or "__all__". '
'Got %s.' % type(fields).__name__
@@ -1043,7 +1047,8 @@ class ModelSerializer(Serializer):
# a subset of fields.
required_field_names = set(declared_fields)
for cls in self.__class__.__bases__:
- required_field_names -= set(getattr(cls, '_declared_fields', []))
+ required_field_names -= set(
+ getattr(cls, '_declared_fields', []))
for field_name in required_field_names:
assert field_name in fields, (
@@ -1101,7 +1106,8 @@ class ModelSerializer(Serializer):
if not nested_depth:
return self.build_relational_field(field_name, relation_info)
else:
- return self.build_nested_field(field_name, relation_info, nested_depth)
+ return self.build_nested_field(field_name, relation_info,
+ nested_depth)
elif hasattr(model_class, field_name):
return self.build_property_field(field_name, model_class)
@@ -1126,7 +1132,8 @@ class ModelSerializer(Serializer):
field_class = self.serializer_choice_field
# Some model fields may introduce kwargs that would not be valid
# for the choice field. We need to strip these out.
- # Eg. models.DecimalField(max_digits=3, decimal_places=1, choices=DECIMAL_CHOICES)
+ # Eg. models.DecimalField(max_digits=3, decimal_places=1, \
+ # choices=DECIMAL_CHOICES)
valid_kwargs = set((
'read_only', 'write_only',
'required', 'default', 'initial', 'source',
@@ -1144,11 +1151,13 @@ class ModelSerializer(Serializer):
# matched to the model field.
field_kwargs.pop('model_field', None)
- if not issubclass(field_class, CharField) and not issubclass(field_class, ChoiceField):
+ if not issubclass(field_class, CharField) and not issubclass(
+ field_class, ChoiceField):
# `allow_blank` is only valid for textual fields.
field_kwargs.pop('allow_blank', None)
- if postgres_fields and isinstance(model_field, postgres_fields.ArrayField):
+ if postgres_fields and isinstance(model_field,
+ postgres_fields.ArrayField):
# Populate the `child` argument on `ListField` instances generated
# for the PostgrSQL specfic `ArrayField`.
child_model_field = model_field.base_field
@@ -1167,7 +1176,9 @@ class ModelSerializer(Serializer):
field_kwargs = get_relation_kwargs(field_name, relation_info)
to_field = field_kwargs.pop('to_field', None)
- if to_field and not relation_info.reverse and not relation_info.related_model._meta.get_field(to_field).primary_key:
+ if to_field and not relation_info.reverse and not \
+ relation_info.related_model._meta.get_field(
+ to_field).primary_key:
field_kwargs['slug_field'] = to_field
field_class = self.serializer_related_to_field
@@ -1181,6 +1192,7 @@ class ModelSerializer(Serializer):
"""
Create nested fields for forward and reverse relationships.
"""
+
class NestedSerializer(ModelSerializer):
class Meta:
model = relation_info.related_model
@@ -1236,7 +1248,8 @@ class ModelSerializer(Serializer):
kwargs.pop('required')
if extra_kwargs.get('read_only', kwargs.get('read_only', False)):
- extra_kwargs.pop('required', None) # Read only fields should always omit the 'required' argument.
+ # Read only fields should always omit the 'required' argument.
+ extra_kwargs.pop('required', None)
kwargs.update(extra_kwargs)
@@ -1249,7 +1262,7 @@ class ModelSerializer(Serializer):
Return a dictionary mapping field names to a dictionary of
additional keyword arguments.
"""
- extra_kwargs = copy.deepcopy(getattr(self.Meta, 'extra_kwargs', {}))
+ extra_kwargs = deepcopy(getattr(self.Meta, 'extra_kwargs', {}))
read_only_fields = getattr(self.Meta, 'read_only_fields', None)
if read_only_fields is not None:
@@ -1265,7 +1278,8 @@ class ModelSerializer(Serializer):
return extra_kwargs
- def get_uniqueness_extra_kwargs(self, field_names, declared_fields, extra_kwargs):
+ def get_uniqueness_extra_kwargs(self, field_names, declared_fields,
+ extra_kwargs):
"""
Return any additional field options that need to be included as a
result of uniqueness constraints on the model. This is returned as
@@ -1288,7 +1302,8 @@ class ModelSerializer(Serializer):
for model_field in model_fields.values():
# Include each of the `unique_for_*` field names.
- unique_constraint_names |= {model_field.unique_for_date, model_field.unique_for_month,
+ unique_constraint_names |= {model_field.unique_for_date,
+ model_field.unique_for_month,
model_field.unique_for_year}
unique_constraint_names -= {None}
@@ -1302,13 +1317,15 @@ class ModelSerializer(Serializer):
# Now we have all the field names that have uniqueness constraints
# applied, we can add the extra 'required=...' or 'default=...'
- # arguments that are appropriate to these fields, or add a `HiddenField` for it.
+ # arguments that are appropriate to these fields, or add a
+ # `HiddenField` for it.
hidden_fields = {}
uniqueness_extra_kwargs = {}
for unique_constraint_name in unique_constraint_names:
# Get the model field that is referred too.
- unique_constraint_field = model._meta.get_field(unique_constraint_name)
+ unique_constraint_field = model._meta.get_field(
+ unique_constraint_name)
if getattr(unique_constraint_field, 'auto_now_add', None):
default = CreateOnlyDefault(timezone.now)
@@ -1322,14 +1339,17 @@ class ModelSerializer(Serializer):
if unique_constraint_name in model_fields:
# The corresponding field is present in the serializer
if default is empty:
- uniqueness_extra_kwargs[unique_constraint_name] = {'required': True}
+ uniqueness_extra_kwargs[unique_constraint_name] = {
+ 'required': True}
else:
- uniqueness_extra_kwargs[unique_constraint_name] = {'default': default}
+ uniqueness_extra_kwargs[unique_constraint_name] = {
+ 'default': default}
elif default is not empty:
# The corresponding field is not present in the
# serializer. We have a default to use for it, so
# add in a hidden field that populates it.
- hidden_fields[unique_constraint_name] = HiddenField(default=default)
+ hidden_fields[unique_constraint_name] = HiddenField(
+ default=default)
# Update `extra_kwargs` with any new options.
for key, value in uniqueness_extra_kwargs.items():
@@ -1393,7 +1413,8 @@ class ModelSerializer(Serializer):
def get_unique_together_validators(self):
"""
- Determine a default set of validators for any unique_together constraints.
+ Determine a default set of validators for any unique_together
+ constraints.
"""
model_class_inheritance_tree = (
[self.Meta.model] +
@@ -1404,10 +1425,8 @@ class ModelSerializer(Serializer):
# which may map onto a model field. Any dotted field name lookups
# cannot map to a field, and must be a traversal, so we're not
# including those.
- field_names = {
- field.source for field in self._writable_fields
- if (field.source != '*') and ('.' not in field.source)
- }
+ field_names = {field.source for field in self._writable_fields
+ if (field.source != '*') and ('.' not in field.source)}
# Note that we make sure to check `unique_together` both on the
# base model class, but also on any parent classes.
@@ -1469,14 +1488,17 @@ if hasattr(models, 'UUIDField'):
# IPAddressField is deprecated in Django
if hasattr(models, 'IPAddressField'):
- ModelSerializer.serializer_field_mapping[models.IPAddressField] = IPAddressField
+ ModelSerializer.serializer_field_mapping[
+ models.IPAddressField] = IPAddressField
if postgres_fields:
class CharMappingField(DictField):
child = CharField(allow_blank=True)
- ModelSerializer.serializer_field_mapping[postgres_fields.HStoreField] = CharMappingField
- ModelSerializer.serializer_field_mapping[postgres_fields.ArrayField] = ListField
+ ModelSerializer.serializer_field_mapping[postgres_fields.HStoreField] = \
+ CharMappingField
+ ModelSerializer.serializer_field_mapping[postgres_fields.ArrayField] = \
+ ListField
class HyperlinkedModelSerializer(ModelSerializer):
@@ -1505,6 +1527,7 @@ class HyperlinkedModelSerializer(ModelSerializer):
"""
Create nested fields for forward and reverse relationships.
"""
+
class NestedSerializer(HyperlinkedModelSerializer):
class Meta:
model = relation_info.related_model
diff --git a/tests/browsable_api/test_form_rendering.py b/tests/browsable_api/test_form_rendering.py
index 8b79ab6ff..a3747ac58 100644
--- a/tests/browsable_api/test_form_rendering.py
+++ b/tests/browsable_api/test_form_rendering.py
@@ -33,10 +33,8 @@ class TestManyPostView(TestCase):
for item in items:
BasicModel(text=item).save()
self.objects = BasicModel.objects
- self.data = [
- {'id': obj.id, 'text': obj.text}
- for obj in self.objects.all()
- ]
+ self.data = [{'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()]
self.view = ManyPostView.as_view()
def test_post_many_post_view(self):
@@ -44,7 +42,8 @@ class TestManyPostView(TestCase):
POST request to a view that returns a list of objects should
still successfully return the browsable API with a rendered form.
- Regression test for https://github.com/tomchristie/django-rest-framework/pull/3164
+ Regression test for
+ https://github.com/tomchristie/django-rest-framework/pull/3164
"""
data = {}
request = factory.post('/', data, format='json')
diff --git a/tests/test_atomic_requests.py b/tests/test_atomic_requests.py
index 09d7f2fb1..8119c2636 100644
--- a/tests/test_atomic_requests.py
+++ b/tests/test_atomic_requests.py
@@ -45,6 +45,7 @@ class NonAtomicAPIExceptionView(APIView):
BasicModel.objects.all()
raise Http404
+
urlpatterns = (
url(r'^$', NonAtomicAPIExceptionView.as_view()),
)
@@ -89,7 +90,8 @@ class DBTransactionErrorTests(TestCase):
Transaction is eventually managed by outer-most transaction atomic
block. DRF do not try to interfere here.
- We let django deal with the transaction when it will catch the Exception.
+ We let django deal with the transaction when it will catch the
+ Exception.
"""
request = factory.post('/')
with self.assertNumQueries(3):
diff --git a/tests/test_fields.py b/tests/test_fields.py
index 6fea249ba..2210f76a4 100644
--- a/tests/test_fields.py
+++ b/tests/test_fields.py
@@ -8,11 +8,19 @@ from decimal import Decimal
import pytest
from django.http import QueryDict
from django.test import TestCase, override_settings
-from django.utils import six, timezone
+from django.utils import timezone
import rest_framework
from rest_framework import serializers
-from rest_framework.fields import is_simple_callable
+from rest_framework.fields import (
+ BooleanField, CharField, ChoiceField, DateField, DateTimeField,
+ DecimalField, DictField, DurationField, EmailField, Field, FileField,
+ FilePathField, FloatField, HiddenField, ImageField, IntegerField,
+ IPAddressField, JSONField, ListField, MultipleChoiceField,
+ NullBooleanField, ReadOnlyField, RegexField, SerializerMethodField,
+ SkipField, SlugField, TimeField, URLField, UUIDField, ValidationError,
+ is_simple_callable, six
+)
try:
import typings
@@ -24,7 +32,6 @@ except ImportError:
# ---------------------------
class TestIsSimpleCallable:
-
def test_method(self):
class Foo:
@classmethod
@@ -82,12 +89,13 @@ class TestEmpty:
"""
Tests for `required`, `allow_null`, `allow_blank`, `default`.
"""
+
def test_required(self):
"""
By default a field must be included in the input.
"""
- field = serializers.IntegerField()
- with pytest.raises(serializers.ValidationError) as exc_info:
+ field = IntegerField()
+ with pytest.raises(ValidationError) as exc_info:
field.run_validation()
assert exc_info.value.detail == ['This field is required.']
@@ -95,16 +103,16 @@ class TestEmpty:
"""
If `required=False` then a field may be omitted from the input.
"""
- field = serializers.IntegerField(required=False)
- with pytest.raises(serializers.SkipField):
+ field = IntegerField(required=False)
+ with pytest.raises(SkipField):
field.run_validation()
def test_disallow_null(self):
"""
By default `None` is not a valid input.
"""
- field = serializers.IntegerField()
- with pytest.raises(serializers.ValidationError) as exc_info:
+ field = IntegerField()
+ with pytest.raises(ValidationError) as exc_info:
field.run_validation(None)
assert exc_info.value.detail == ['This field may not be null.']
@@ -112,7 +120,7 @@ class TestEmpty:
"""
If `allow_null=True` then `None` is a valid input.
"""
- field = serializers.IntegerField(allow_null=True)
+ field = IntegerField(allow_null=True)
output = field.run_validation(None)
assert output is None
@@ -120,8 +128,8 @@ class TestEmpty:
"""
By default '' is not a valid input.
"""
- field = serializers.CharField()
- with pytest.raises(serializers.ValidationError) as exc_info:
+ field = CharField()
+ with pytest.raises(ValidationError) as exc_info:
field.run_validation('')
assert exc_info.value.detail == ['This field may not be blank.']
@@ -129,7 +137,7 @@ class TestEmpty:
"""
If `allow_blank=True` then '' is a valid input.
"""
- field = serializers.CharField(allow_blank=True)
+ field = CharField(allow_blank=True)
output = field.run_validation('')
assert output == ''
@@ -137,7 +145,7 @@ class TestEmpty:
"""
If `default` is set, then omitted values get the default input.
"""
- field = serializers.IntegerField(default=123)
+ field = IntegerField(default=123)
output = field.run_validation()
assert output is 123
@@ -145,14 +153,16 @@ class TestEmpty:
class TestSource:
def test_source(self):
class ExampleSerializer(serializers.Serializer):
- example_field = serializers.CharField(source='other')
+ example_field = CharField(source='other')
+
serializer = ExampleSerializer(data={'example_field': 'abc'})
assert serializer.is_valid()
assert serializer.validated_data == {'other': 'abc'}
def test_redundant_source(self):
class ExampleSerializer(serializers.Serializer):
- example_field = serializers.CharField(source='example_field')
+ example_field = CharField(source='example_field')
+
with pytest.raises(AssertionError) as exc_info:
ExampleSerializer().fields
assert str(exc_info.value) == (
@@ -163,7 +173,7 @@ class TestSource:
def test_callable_source(self):
class ExampleSerializer(serializers.Serializer):
- example_field = serializers.CharField(source='example_callable')
+ example_field = CharField(source='example_callable')
class ExampleInstance(object):
def example_callable(self):
@@ -174,7 +184,8 @@ class TestSource:
def test_callable_source_raises(self):
class ExampleSerializer(serializers.Serializer):
- example_field = serializers.CharField(source='example_callable', read_only=True)
+ example_field = CharField(source='example_callable',
+ read_only=True)
class ExampleInstance(object):
def example_callable(self):
@@ -190,13 +201,14 @@ class TestSource:
class TestReadOnly:
def setup(self):
class TestSerializer(serializers.Serializer):
- read_only = serializers.ReadOnlyField()
- writable = serializers.IntegerField()
+ read_only = ReadOnlyField()
+ writable = IntegerField()
+
self.Serializer = TestSerializer
def test_validate_read_only(self):
"""
- Read-only serializers.should not be included in validation.
+ Read-only should not be included in validation.
"""
data = {'read_only': 123, 'writable': 456}
serializer = self.Serializer(data=data)
@@ -205,7 +217,7 @@ class TestReadOnly:
def test_serialize_read_only(self):
"""
- Read-only serializers.should be serialized.
+ Read-only should be serialized.
"""
instance = {'read_only': 123, 'writable': 456}
serializer = self.Serializer(instance)
@@ -215,22 +227,24 @@ class TestReadOnly:
class TestWriteOnly:
def setup(self):
class TestSerializer(serializers.Serializer):
- write_only = serializers.IntegerField(write_only=True)
- readable = serializers.IntegerField()
+ write_only = IntegerField(write_only=True)
+ readable = IntegerField()
+
self.Serializer = TestSerializer
def test_validate_write_only(self):
"""
- Write-only serializers.should be included in validation.
+ Write-only should be included in validation.
"""
data = {'write_only': 123, 'readable': 456}
serializer = self.Serializer(data=data)
assert serializer.is_valid()
- assert serializer.validated_data == {'write_only': 123, 'readable': 456}
+ assert serializer.validated_data == {'write_only': 123,
+ 'readable': 456}
def test_serialize_write_only(self):
"""
- Write-only serializers.should not be serialized.
+ Write-only should not be serialized.
"""
instance = {'write_only': 123, 'readable': 456}
serializer = self.Serializer(instance)
@@ -240,13 +254,14 @@ class TestWriteOnly:
class TestInitial:
def setup(self):
class TestSerializer(serializers.Serializer):
- initial_field = serializers.IntegerField(initial=123)
- blank_field = serializers.IntegerField()
+ initial_field = IntegerField(initial=123)
+ blank_field = IntegerField()
+
self.serializer = TestSerializer()
def test_initial(self):
"""
- Initial values should be included when serializing a new representation.
+ Initial values should be included when serializing a new representation
"""
assert self.serializer.data == {
'initial_field': 123,
@@ -260,7 +275,8 @@ class TestInitialWithCallable:
return 123
class TestSerializer(serializers.Serializer):
- initial_field = serializers.IntegerField(initial=initial_value)
+ initial_field = IntegerField(initial=initial_value)
+
self.serializer = TestSerializer()
def test_initial_should_accept_callable(self):
@@ -275,7 +291,8 @@ class TestInitialWithCallable:
class TestLabel:
def setup(self):
class TestSerializer(serializers.Serializer):
- labeled = serializers.IntegerField(label='My label')
+ labeled = IntegerField(label='My label')
+
self.serializer = TestSerializer()
def test_label(self):
@@ -288,9 +305,10 @@ class TestLabel:
class TestInvalidErrorKey:
def setup(self):
- class ExampleField(serializers.Field):
+ class ExampleField(Field):
def to_native(self, data):
self.fail('incorrect')
+
self.field = ExampleField()
def test_invalid_error_key(self):
@@ -313,8 +331,9 @@ class TestBooleanHTMLInput:
HTML checkboxes do not send any value, but should be treated
as `False` by BooleanField.
"""
+
class TestSerializer(serializers.Serializer):
- archived = serializers.BooleanField()
+ archived = BooleanField()
serializer = TestSerializer(data=QueryDict(''))
assert serializer.is_valid()
@@ -325,8 +344,9 @@ class TestBooleanHTMLInput:
HTML checkboxes do not send any value, but should be treated
as `False` by BooleanField, even if the field is required=False.
"""
+
class TestSerializer(serializers.Serializer):
- archived = serializers.BooleanField(required=False)
+ archived = BooleanField(required=False)
serializer = TestSerializer(data=QueryDict(''))
assert serializer.is_valid()
@@ -336,7 +356,7 @@ class TestBooleanHTMLInput:
class TestHTMLInput:
def test_empty_html_charfield_with_default(self):
class TestSerializer(serializers.Serializer):
- message = serializers.CharField(default='happy')
+ message = CharField(default='happy')
serializer = TestSerializer(data=QueryDict(''))
assert serializer.is_valid()
@@ -344,7 +364,7 @@ class TestHTMLInput:
def test_empty_html_charfield_without_default(self):
class TestSerializer(serializers.Serializer):
- message = serializers.CharField(allow_blank=True)
+ message = CharField(allow_blank=True)
serializer = TestSerializer(data=QueryDict('message='))
assert serializer.is_valid()
@@ -352,7 +372,7 @@ class TestHTMLInput:
def test_empty_html_charfield_without_default_not_required(self):
class TestSerializer(serializers.Serializer):
- message = serializers.CharField(allow_blank=True, required=False)
+ message = CharField(allow_blank=True, required=False)
serializer = TestSerializer(data=QueryDict('message='))
assert serializer.is_valid()
@@ -360,7 +380,7 @@ class TestHTMLInput:
def test_empty_html_integerfield(self):
class TestSerializer(serializers.Serializer):
- message = serializers.IntegerField(default=123)
+ message = IntegerField(default=123)
serializer = TestSerializer(data=QueryDict('message='))
assert serializer.is_valid()
@@ -368,7 +388,7 @@ class TestHTMLInput:
def test_empty_html_uuidfield_with_default(self):
class TestSerializer(serializers.Serializer):
- message = serializers.UUIDField(default=uuid.uuid4)
+ message = UUIDField(default=uuid.uuid4)
serializer = TestSerializer(data=QueryDict('message='))
assert serializer.is_valid()
@@ -376,7 +396,7 @@ class TestHTMLInput:
def test_empty_html_uuidfield_with_optional(self):
class TestSerializer(serializers.Serializer):
- message = serializers.UUIDField(required=False)
+ message = UUIDField(required=False)
serializer = TestSerializer(data=QueryDict('message='))
assert serializer.is_valid()
@@ -384,7 +404,7 @@ class TestHTMLInput:
def test_empty_html_charfield_allow_null(self):
class TestSerializer(serializers.Serializer):
- message = serializers.CharField(allow_null=True)
+ message = CharField(allow_null=True)
serializer = TestSerializer(data=QueryDict('message='))
assert serializer.is_valid()
@@ -392,7 +412,7 @@ class TestHTMLInput:
def test_empty_html_datefield_allow_null(self):
class TestSerializer(serializers.Serializer):
- expiry = serializers.DateField(allow_null=True)
+ expiry = DateField(allow_null=True)
serializer = TestSerializer(data=QueryDict('expiry='))
assert serializer.is_valid()
@@ -400,7 +420,7 @@ class TestHTMLInput:
def test_empty_html_charfield_allow_null_allow_blank(self):
class TestSerializer(serializers.Serializer):
- message = serializers.CharField(allow_null=True, allow_blank=True)
+ message = CharField(allow_null=True, allow_blank=True)
serializer = TestSerializer(data=QueryDict('message='))
assert serializer.is_valid()
@@ -408,7 +428,7 @@ class TestHTMLInput:
def test_empty_html_charfield_required_false(self):
class TestSerializer(serializers.Serializer):
- message = serializers.CharField(required=False)
+ message = CharField(required=False)
serializer = TestSerializer(data=QueryDict(''))
assert serializer.is_valid()
@@ -416,7 +436,7 @@ class TestHTMLInput:
def test_querydict_list_input(self):
class TestSerializer(serializers.Serializer):
- scores = serializers.ListField(child=serializers.IntegerField())
+ scores = ListField(child=IntegerField())
serializer = TestSerializer(data=QueryDict('scores=1&scores=3'))
assert serializer.is_valid()
@@ -424,7 +444,7 @@ class TestHTMLInput:
def test_querydict_list_input_only_one_input(self):
class TestSerializer(serializers.Serializer):
- scores = serializers.ListField(child=serializers.IntegerField())
+ scores = ListField(child=IntegerField())
serializer = TestSerializer(data=QueryDict('scores=1&'))
assert serializer.is_valid()
@@ -436,8 +456,9 @@ class TestCreateOnlyDefault:
default = serializers.CreateOnlyDefault('2001-01-01')
class TestSerializer(serializers.Serializer):
- published = serializers.HiddenField(default=default)
- text = serializers.CharField()
+ published = HiddenField(default=default)
+ text = CharField()
+
self.Serializer = TestSerializer
def test_create_only_default_is_provided(self):
@@ -462,6 +483,7 @@ class TestCreateOnlyDefault:
CreateOnlyDefault instances with a callable default should set_context
on the callable if possible
"""
+
class TestCallableDefault:
def set_context(self, serializer_field):
self.field = serializer_field
@@ -470,7 +492,8 @@ class TestCreateOnlyDefault:
return "success" if hasattr(self, 'field') else "failure"
class TestSerializer(serializers.Serializer):
- context_set = serializers.CharField(default=serializers.CreateOnlyDefault(TestCallableDefault()))
+ context_set = CharField(
+ default=serializers.CreateOnlyDefault(TestCallableDefault()))
serializer = TestSerializer(data={})
assert serializer.is_valid()
@@ -493,6 +516,7 @@ class FieldValues:
"""
Base class for testing valid and invalid input values.
"""
+
def test_valid_inputs(self):
"""
Ensure that valid values return the expected validated data.
@@ -505,13 +529,14 @@ class FieldValues:
Ensure that invalid values raise the expected validation error.
"""
for input_value, expected_failure in get_items(self.invalid_inputs):
- with pytest.raises(serializers.ValidationError) as exc_info:
+ with pytest.raises(ValidationError) as exc_info:
self.field.run_validation(input_value)
assert exc_info.value.detail == expected_failure
def test_outputs(self):
for output_value, expected_output in get_items(self.outputs):
- assert self.field.to_representation(output_value) == expected_output
+ assert self.field.to_representation(
+ output_value) == expected_output
# Boolean types...
@@ -545,16 +570,16 @@ class TestBooleanField(FieldValues):
False: False,
'other': True
}
- field = serializers.BooleanField()
+ field = BooleanField()
def test_disallow_unhashable_collection_types(self):
inputs = (
[],
{},
)
- field = serializers.BooleanField()
+ field = BooleanField()
for input_value in inputs:
- with pytest.raises(serializers.ValidationError) as exc_info:
+ with pytest.raises(ValidationError) as exc_info:
field.run_validation(input_value)
expected = ['"{0}" is not a valid boolean.'.format(input_value)]
assert exc_info.value.detail == expected
@@ -584,7 +609,7 @@ class TestNullBooleanField(FieldValues):
None: None,
'other': True
}
- field = serializers.NullBooleanField()
+ field = NullBooleanField()
# String types...
@@ -606,20 +631,20 @@ class TestCharField(FieldValues):
1: '1',
'abc': 'abc'
}
- field = serializers.CharField()
+ field = CharField()
def test_trim_whitespace_default(self):
- field = serializers.CharField()
+ field = CharField()
assert field.to_internal_value(' abc ') == 'abc'
def test_trim_whitespace_disabled(self):
- field = serializers.CharField(trim_whitespace=False)
+ field = CharField(trim_whitespace=False)
assert field.to_internal_value(' abc ') == ' abc '
def test_disallow_blank_with_trim_whitespace(self):
- field = serializers.CharField(allow_blank=False, trim_whitespace=True)
+ field = CharField(allow_blank=False, trim_whitespace=True)
- with pytest.raises(serializers.ValidationError) as exc_info:
+ with pytest.raises(ValidationError) as exc_info:
field.run_validation(' ')
assert exc_info.value.detail == ['This field may not be blank.']
@@ -636,7 +661,7 @@ class TestEmailField(FieldValues):
'examplecom': ['Enter a valid email address.']
}
outputs = {}
- field = serializers.EmailField()
+ field = EmailField()
class TestRegexField(FieldValues):
@@ -650,7 +675,7 @@ class TestRegexField(FieldValues):
'A9': ["This value does not match the required pattern."]
}
outputs = {}
- field = serializers.RegexField(regex='[a-z][0-9]')
+ field = RegexField(regex='[a-z][0-9]')
class TestiCompiledRegexField(FieldValues):
@@ -664,7 +689,7 @@ class TestiCompiledRegexField(FieldValues):
'A9': ["This value does not match the required pattern."]
}
outputs = {}
- field = serializers.RegexField(regex=re.compile('[a-z][0-9]'))
+ field = RegexField(regex=re.compile('[a-z][0-9]'))
class TestSlugField(FieldValues):
@@ -675,10 +700,12 @@ class TestSlugField(FieldValues):
'slug-99': 'slug-99',
}
invalid_inputs = {
- 'slug 99': ['Enter a valid "slug" consisting of letters, numbers, underscores or hyphens.']
+ 'slug 99': [
+ 'Enter a valid "slug" consisting of letters, numbers, underscores '
+ 'or hyphens.']
}
outputs = {}
- field = serializers.SlugField()
+ field = SlugField()
class TestURLField(FieldValues):
@@ -692,7 +719,7 @@ class TestURLField(FieldValues):
'example.com': ['Enter a valid URL.']
}
outputs = {}
- field = serializers.URLField()
+ field = URLField()
class TestUUIDField(FieldValues):
@@ -700,29 +727,37 @@ class TestUUIDField(FieldValues):
Valid and invalid values for `UUIDField`.
"""
valid_inputs = {
- '825d7aeb-05a9-45b5-a5b7-05df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'),
- '825d7aeb05a945b5a5b705df87923cda': uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'),
- 'urn:uuid:213b7d9b-244f-410d-828c-dabce7a2615d': uuid.UUID('213b7d9b-244f-410d-828c-dabce7a2615d'),
- 284758210125106368185219588917561929842: uuid.UUID('d63a6fb6-88d5-40c7-a91c-9edf73283072')
+ '825d7aeb-05a9-45b5-a5b7-05df87923cda': uuid.UUID(
+ '825d7aeb-05a9-45b5-a5b7-05df87923cda'),
+ '825d7aeb05a945b5a5b705df87923cda': uuid.UUID(
+ '825d7aeb-05a9-45b5-a5b7-05df87923cda'),
+ 'urn:uuid:213b7d9b-244f-410d-828c-dabce7a2615d': uuid.UUID(
+ '213b7d9b-244f-410d-828c-dabce7a2615d'),
+ 284758210125106368185219588917561929842: uuid.UUID(
+ 'd63a6fb6-88d5-40c7-a91c-9edf73283072')
}
invalid_inputs = {
- '825d7aeb-05a9-45b5-a5b7': ['"825d7aeb-05a9-45b5-a5b7" is not a valid UUID.'],
+ '825d7aeb-05a9-45b5-a5b7': [
+ '"825d7aeb-05a9-45b5-a5b7" is not a valid UUID.'],
(1, 2, 3): ['"(1, 2, 3)" is not a valid UUID.']
}
outputs = {
- uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'): '825d7aeb-05a9-45b5-a5b7-05df87923cda'
+ uuid.UUID('825d7aeb-05a9-45b5-a5b7-05df87923cda'):
+ '825d7aeb-05a9-45b5-a5b7-05df87923cda'
}
- field = serializers.UUIDField()
+ field = UUIDField()
def _test_format(self, uuid_format, formatted_uuid_0):
- field = serializers.UUIDField(format=uuid_format)
+ field = UUIDField(format=uuid_format)
assert field.to_representation(uuid.UUID(int=0)) == formatted_uuid_0
assert field.to_internal_value(formatted_uuid_0) == uuid.UUID(int=0)
def test_formats(self):
self._test_format('int', 0)
- self._test_format('hex_verbose', '00000000-0000-0000-0000-000000000000')
- self._test_format('urn', 'urn:uuid:00000000-0000-0000-0000-000000000000')
+ self._test_format('hex_verbose',
+ '00000000-0000-0000-0000-000000000000')
+ self._test_format('urn',
+ 'urn:uuid:00000000-0000-0000-0000-000000000000')
self._test_format('hex', '0' * 32)
@@ -733,7 +768,8 @@ class TestIPAddressField(FieldValues):
valid_inputs = {
'127.0.0.1': '127.0.0.1',
'192.168.33.255': '192.168.33.255',
- '2001:0db8:85a3:0042:1000:8a2e:0370:7334': '2001:db8:85a3:42:1000:8a2e:370:7334',
+ '2001:0db8:85a3:0042:1000:8a2e:0370:7334':
+ '2001:db8:85a3:42:1000:8a2e:370:7334',
'2001:cdba:0:0:0:0:3257:9652': '2001:cdba::3257:9652',
'2001:cdba::3257:9652': '2001:cdba::3257:9652'
}
@@ -741,11 +777,12 @@ class TestIPAddressField(FieldValues):
'127001': ['Enter a valid IPv4 or IPv6 address.'],
'127.122.111.2231': ['Enter a valid IPv4 or IPv6 address.'],
'2001:::9652': ['Enter a valid IPv4 or IPv6 address.'],
- '2001:0db8:85a3:0042:1000:8a2e:0370:73341': ['Enter a valid IPv4 or IPv6 address.'],
+ '2001:0db8:85a3:0042:1000:8a2e:0370:73341': [
+ 'Enter a valid IPv4 or IPv6 address.'],
1000: ['Enter a valid IPv4 or IPv6 address.'],
}
outputs = {}
- field = serializers.IPAddressField()
+ field = IPAddressField()
class TestIPv4AddressField(FieldValues):
@@ -761,7 +798,7 @@ class TestIPv4AddressField(FieldValues):
'127.122.111.2231': ['Enter a valid IPv4 address.'],
}
outputs = {}
- field = serializers.IPAddressField(protocol='IPv4')
+ field = IPAddressField(protocol='IPv4')
class TestIPv6AddressField(FieldValues):
@@ -769,16 +806,18 @@ class TestIPv6AddressField(FieldValues):
Valid and invalid values for `IPAddressField`
"""
valid_inputs = {
- '2001:0db8:85a3:0042:1000:8a2e:0370:7334': '2001:db8:85a3:42:1000:8a2e:370:7334',
+ '2001:0db8:85a3:0042:1000:8a2e:0370:7334':
+ '2001:db8:85a3:42:1000:8a2e:370:7334',
'2001:cdba:0:0:0:0:3257:9652': '2001:cdba::3257:9652',
'2001:cdba::3257:9652': '2001:cdba::3257:9652'
}
invalid_inputs = {
'2001:::9652': ['Enter a valid IPv4 or IPv6 address.'],
- '2001:0db8:85a3:0042:1000:8a2e:0370:73341': ['Enter a valid IPv4 or IPv6 address.'],
+ '2001:0db8:85a3:0042:1000:8a2e:0370:73341': [
+ 'Enter a valid IPv4 or IPv6 address.'],
}
outputs = {}
- field = serializers.IPAddressField(protocol='IPv6')
+ field = IPAddressField(protocol='IPv6')
class TestFilePathField(FieldValues):
@@ -794,7 +833,7 @@ class TestFilePathField(FieldValues):
}
outputs = {
}
- field = serializers.FilePathField(
+ field = FilePathField(
path=os.path.abspath(os.path.dirname(__file__))
)
@@ -827,7 +866,7 @@ class TestIntegerField(FieldValues):
1.0: 1,
0.0: 0
}
- field = serializers.IntegerField()
+ field = IntegerField()
class TestMinMaxIntegerField(FieldValues):
@@ -847,7 +886,7 @@ class TestMinMaxIntegerField(FieldValues):
'4': ['Ensure this value is less than or equal to 3.'],
}
outputs = {}
- field = serializers.IntegerField(min_value=1, max_value=3)
+ field = IntegerField(min_value=1, max_value=3)
class TestFloatField(FieldValues):
@@ -873,7 +912,7 @@ class TestFloatField(FieldValues):
1.0: 1.0,
0.0: 0.0,
}
- field = serializers.FloatField()
+ field = FloatField()
class TestMinMaxFloatField(FieldValues):
@@ -895,7 +934,7 @@ class TestMinMaxFloatField(FieldValues):
'3.1': ['Ensure this value is less than or equal to 3.'],
}
outputs = {}
- field = serializers.FloatField(min_value=1, max_value=3)
+ field = FloatField(min_value=1, max_value=3)
class TestDecimalField(FieldValues):
@@ -916,10 +955,15 @@ class TestDecimalField(FieldValues):
(Decimal('Nan'), ["A valid number is required."]),
(Decimal('Inf'), ["A valid number is required."]),
('12.345', ["Ensure that there are no more than 3 digits in total."]),
- (200000000000.0, ["Ensure that there are no more than 3 digits in total."]),
+ (200000000000.0,
+ ["Ensure that there are no more than 3 digits in total."]),
('0.01', ["Ensure that there are no more than 1 decimal places."]),
- (123, ["Ensure that there are no more than 2 digits before the decimal point."]),
- ('2E+2', ["Ensure that there are no more than 2 digits before the decimal point."])
+ (123, [
+ "Ensure that there are no more than 2 digits before the decimal "
+ "point."]),
+ ('2E+2', [
+ "Ensure that there are no more than 2 digits before the decimal "
+ "point."])
)
outputs = {
'1': '1.0',
@@ -933,7 +977,7 @@ class TestDecimalField(FieldValues):
Decimal('1.09'): '1.1',
Decimal('0.04'): '0.0'
}
- field = serializers.DecimalField(max_digits=3, decimal_places=1)
+ field = DecimalField(max_digits=3, decimal_places=1)
class TestMinMaxDecimalField(FieldValues):
@@ -949,14 +993,14 @@ class TestMinMaxDecimalField(FieldValues):
'20.1': ['Ensure this value is less than or equal to 20.'],
}
outputs = {}
- field = serializers.DecimalField(
+ field = DecimalField(
max_digits=3, decimal_places=1,
min_value=10, max_value=20
)
class TestNoMaxDigitsDecimalField(FieldValues):
- field = serializers.DecimalField(
+ field = DecimalField(
max_value=100, min_value=0,
decimal_places=2, max_digits=None
)
@@ -981,7 +1025,7 @@ class TestNoStringCoercionDecimalField(FieldValues):
Decimal('1.09'): Decimal('1.1'),
Decimal('0.04'): Decimal('0.0'),
}
- field = serializers.DecimalField(
+ field = DecimalField(
max_digits=3, decimal_places=1,
coerce_to_string=False
)
@@ -990,34 +1034,36 @@ class TestNoStringCoercionDecimalField(FieldValues):
class TestLocalizedDecimalField(TestCase):
@override_settings(USE_L10N=True, LANGUAGE_CODE='pl')
def test_to_internal_value(self):
- field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True)
+ field = DecimalField(max_digits=2, decimal_places=1, localize=True)
self.assertEqual(field.to_internal_value('1,1'), Decimal('1.1'))
@override_settings(USE_L10N=True, LANGUAGE_CODE='pl')
def test_to_representation(self):
- field = serializers.DecimalField(max_digits=2, decimal_places=1, localize=True)
+ field = DecimalField(max_digits=2, decimal_places=1, localize=True)
self.assertEqual(field.to_representation(Decimal('1.1')), '1,1')
def test_localize_forces_coerce_to_string(self):
- field = serializers.DecimalField(max_digits=2, decimal_places=1, coerce_to_string=False, localize=True)
- self.assertTrue(isinstance(field.to_representation(Decimal('1.1')), six.string_types))
+ field = DecimalField(max_digits=2, decimal_places=1,
+ coerce_to_string=False, localize=True)
+ self.assertTrue(isinstance(field.to_representation(Decimal('1.1')),
+ six.string_types))
class TestQuantizedValueForDecimal(TestCase):
def test_int_quantized_value_for_decimal(self):
- field = serializers.DecimalField(max_digits=4, decimal_places=2)
+ field = DecimalField(max_digits=4, decimal_places=2)
value = field.to_internal_value(12).as_tuple()
expected_digit_tuple = (0, (1, 2, 0, 0), -2)
self.assertEqual(value, expected_digit_tuple)
def test_string_quantized_value_for_decimal(self):
- field = serializers.DecimalField(max_digits=4, decimal_places=2)
+ field = DecimalField(max_digits=4, decimal_places=2)
value = field.to_internal_value('12').as_tuple()
expected_digit_tuple = (0, (1, 2, 0, 0), -2)
self.assertEqual(value, expected_digit_tuple)
def test_part_precision_string_quantized_value_for_decimal(self):
- field = serializers.DecimalField(max_digits=4, decimal_places=2)
+ field = DecimalField(max_digits=4, decimal_places=2)
value = field.to_internal_value('12.0').as_tuple()
expected_digit_tuple = (0, (1, 2, 0, 0), -2)
self.assertEqual(value, expected_digit_tuple)
@@ -1035,10 +1081,10 @@ class TestNoDecimalPlaces(FieldValues):
'0': '0',
'1.1': '1.1',
}
- field = serializers.DecimalField(max_digits=6, decimal_places=None)
+ field = DecimalField(max_digits=6, decimal_places=None)
-# Date & time serializers...
+# Date & time ..
class TestDateField(FieldValues):
"""
@@ -1049,9 +1095,14 @@ class TestDateField(FieldValues):
datetime.date(2001, 1, 1): datetime.date(2001, 1, 1),
}
invalid_inputs = {
- 'abc': ['Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].'],
- '2001-99-99': ['Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]].'],
- datetime.datetime(2001, 1, 1, 12, 00): ['Expected a date but got a datetime.'],
+ 'abc': [
+ 'Date has wrong format. Use one of these formats instead: '
+ 'YYYY[-MM[-DD]].'],
+ '2001-99-99': [
+ 'Date has wrong format. Use one of these formats instead: '
+ 'YYYY[-MM[-DD]].'],
+ datetime.datetime(2001, 1, 1, 12, 00): [
+ 'Expected a date but got a datetime.'],
}
outputs = {
datetime.date(2001, 1, 1): '2001-01-01',
@@ -1060,7 +1111,7 @@ class TestDateField(FieldValues):
None: None,
'': None,
}
- field = serializers.DateField()
+ field = DateField()
class TestCustomInputFormatDateField(FieldValues):
@@ -1071,10 +1122,12 @@ class TestCustomInputFormatDateField(FieldValues):
'1 Jan 2001': datetime.date(2001, 1, 1),
}
invalid_inputs = {
- '2001-01-01': ['Date has wrong format. Use one of these formats instead: DD [Jan-Dec] YYYY.']
+ '2001-01-01': [
+ 'Date has wrong format. Use one of these formats instead: '
+ 'DD [Jan-Dec] YYYY.']
}
outputs = {}
- field = serializers.DateField(input_formats=['%d %b %Y'])
+ field = DateField(input_formats=['%d %b %Y'])
class TestCustomOutputFormatDateField(FieldValues):
@@ -1086,7 +1139,7 @@ class TestCustomOutputFormatDateField(FieldValues):
outputs = {
datetime.date(2001, 1, 1): '01 Jan 2001'
}
- field = serializers.DateField(format='%d %b %Y')
+ field = DateField(format='%d %b %Y')
class TestNoOutputFormatDateField(FieldValues):
@@ -1098,7 +1151,7 @@ class TestNoOutputFormatDateField(FieldValues):
outputs = {
datetime.date(2001, 1, 1): datetime.date(2001, 1, 1)
}
- field = serializers.DateField(format=None)
+ field = DateField(format=None)
class TestDateTimeField(FieldValues):
@@ -1106,28 +1159,40 @@ class TestDateTimeField(FieldValues):
Valid and invalid values for `DateTimeField`.
"""
valid_inputs = {
- '2001-01-01 13:00': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()),
- '2001-01-01T13:00': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()),
- '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()),
- datetime.datetime(2001, 1, 1, 13, 00): datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()),
- datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()): datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()),
+ '2001-01-01 13:00': datetime.datetime(2001, 1, 1, 13, 00,
+ tzinfo=timezone.UTC()),
+ '2001-01-01T13:00': datetime.datetime(2001, 1, 1, 13, 00,
+ tzinfo=timezone.UTC()),
+ '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00,
+ tzinfo=timezone.UTC()),
+ datetime.datetime(2001, 1, 1, 13, 00):
+ datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()),
+ datetime.datetime(2001, 1, 1, 13, 00,
+ tzinfo=timezone.UTC()):
+ datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()),
# Django 1.4 does not support timezone string parsing.
- '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC())
+ '2001-01-01T13:00Z': datetime.datetime(2001, 1, 1, 13, 00,
+ tzinfo=timezone.UTC())
}
invalid_inputs = {
- 'abc': ['Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].'],
- '2001-99-99T99:00': ['Datetime has wrong format. Use one of these formats instead: YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].'],
+ 'abc': [
+ 'Datetime has wrong format. Use one of these formats instead: '
+ 'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].'],
+ '2001-99-99T99:00': [
+ 'Datetime has wrong format. Use one of these formats instead: '
+ 'YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z].'],
datetime.date(2001, 1, 1): ['Expected a datetime but got a date.'],
}
outputs = {
datetime.datetime(2001, 1, 1, 13, 00): '2001-01-01T13:00:00',
- datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()): '2001-01-01T13:00:00Z',
+ datetime.datetime(2001, 1, 1, 13, 00,
+ tzinfo=timezone.UTC()): '2001-01-01T13:00:00Z',
'2001-01-01T00:00:00': '2001-01-01T00:00:00',
six.text_type('2016-01-10T00:00:00'): '2016-01-10T00:00:00',
None: None,
'': None,
}
- field = serializers.DateTimeField(default_timezone=timezone.UTC())
+ field = DateTimeField(default_timezone=timezone.UTC())
class TestCustomInputFormatDateTimeField(FieldValues):
@@ -1135,13 +1200,17 @@ class TestCustomInputFormatDateTimeField(FieldValues):
Valid and invalid values for `DateTimeField` with a custom input format.
"""
valid_inputs = {
- '1:35pm, 1 Jan 2001': datetime.datetime(2001, 1, 1, 13, 35, tzinfo=timezone.UTC()),
+ '1:35pm, 1 Jan 2001': datetime.datetime(2001, 1, 1, 13, 35,
+ tzinfo=timezone.UTC()),
}
invalid_inputs = {
- '2001-01-01T20:50': ['Datetime has wrong format. Use one of these formats instead: hh:mm[AM|PM], DD [Jan-Dec] YYYY.']
+ '2001-01-01T20:50': [
+ 'Datetime has wrong format. Use one of these formats instead: '
+ 'hh:mm[AM|PM], DD [Jan-Dec] YYYY.']
}
outputs = {}
- field = serializers.DateTimeField(default_timezone=timezone.UTC(), input_formats=['%I:%M%p, %d %b %Y'])
+ field = DateTimeField(default_timezone=timezone.UTC(),
+ input_formats=['%I:%M%p, %d %b %Y'])
class TestCustomOutputFormatDateTimeField(FieldValues):
@@ -1153,7 +1222,7 @@ class TestCustomOutputFormatDateTimeField(FieldValues):
outputs = {
datetime.datetime(2001, 1, 1, 13, 00): '01:00PM, 01 Jan 2001',
}
- field = serializers.DateTimeField(format='%I:%M%p, %d %b %Y')
+ field = DateTimeField(format='%I:%M%p, %d %b %Y')
class TestNoOutputFormatDateTimeField(FieldValues):
@@ -1163,9 +1232,10 @@ class TestNoOutputFormatDateTimeField(FieldValues):
valid_inputs = {}
invalid_inputs = {}
outputs = {
- datetime.datetime(2001, 1, 1, 13, 00): datetime.datetime(2001, 1, 1, 13, 00),
+ datetime.datetime(2001, 1, 1, 13, 00): datetime.datetime(2001, 1, 1,
+ 13, 00),
}
- field = serializers.DateTimeField(format=None)
+ field = DateTimeField(format=None)
class TestNaiveDateTimeField(FieldValues):
@@ -1173,12 +1243,14 @@ class TestNaiveDateTimeField(FieldValues):
Valid and invalid values for `DateTimeField` with naive datetimes.
"""
valid_inputs = {
- datetime.datetime(2001, 1, 1, 13, 00, tzinfo=timezone.UTC()): datetime.datetime(2001, 1, 1, 13, 00),
+ datetime.datetime(2001, 1, 1, 13, 00,
+ tzinfo=timezone.UTC()): datetime.datetime(2001, 1, 1,
+ 13, 00),
'2001-01-01 13:00': datetime.datetime(2001, 1, 1, 13, 00),
}
invalid_inputs = {}
outputs = {}
- field = serializers.DateTimeField(default_timezone=None)
+ field = DateTimeField(default_timezone=None)
class TestTimeField(FieldValues):
@@ -1190,8 +1262,12 @@ class TestTimeField(FieldValues):
datetime.time(13, 00): datetime.time(13, 00),
}
invalid_inputs = {
- 'abc': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]].'],
- '99:99': ['Time has wrong format. Use one of these formats instead: hh:mm[:ss[.uuuuuu]].'],
+ 'abc': [
+ 'Time has wrong format. Use one of these formats instead: '
+ 'hh:mm[:ss[.uuuuuu]].'],
+ '99:99': [
+ 'Time has wrong format. Use one of these formats instead: '
+ 'hh:mm[:ss[.uuuuuu]].'],
}
outputs = {
datetime.time(13, 0): '13:00:00',
@@ -1200,7 +1276,7 @@ class TestTimeField(FieldValues):
None: None,
'': None,
}
- field = serializers.TimeField()
+ field = TimeField()
class TestCustomInputFormatTimeField(FieldValues):
@@ -1211,10 +1287,12 @@ class TestCustomInputFormatTimeField(FieldValues):
'1:00pm': datetime.time(13, 00),
}
invalid_inputs = {
- '13:00': ['Time has wrong format. Use one of these formats instead: hh:mm[AM|PM].'],
+ '13:00': [
+ 'Time has wrong format. Use one of these formats instead: '
+ 'hh:mm[AM|PM].'],
}
outputs = {}
- field = serializers.TimeField(input_formats=['%I:%M%p'])
+ field = TimeField(input_formats=['%I:%M%p'])
class TestCustomOutputFormatTimeField(FieldValues):
@@ -1226,7 +1304,7 @@ class TestCustomOutputFormatTimeField(FieldValues):
outputs = {
datetime.time(13, 00): '01:00PM'
}
- field = serializers.TimeField(format='%I:%M%p')
+ field = TimeField(format='%I:%M%p')
class TestNoOutputFormatTimeField(FieldValues):
@@ -1238,7 +1316,7 @@ class TestNoOutputFormatTimeField(FieldValues):
outputs = {
datetime.time(13, 00): datetime.time(13, 00)
}
- field = serializers.TimeField(format=None)
+ field = TimeField(format=None)
class TestDurationField(FieldValues):
@@ -1247,19 +1325,30 @@ class TestDurationField(FieldValues):
"""
valid_inputs = {
'13': datetime.timedelta(seconds=13),
- '3 08:32:01.000123': datetime.timedelta(days=3, hours=8, minutes=32, seconds=1, microseconds=123),
+ '3 08:32:01.000123': datetime.timedelta(days=3, hours=8, minutes=32,
+ seconds=1, microseconds=123),
'08:01': datetime.timedelta(minutes=8, seconds=1),
- datetime.timedelta(days=3, hours=8, minutes=32, seconds=1, microseconds=123): datetime.timedelta(days=3, hours=8, minutes=32, seconds=1, microseconds=123),
+ datetime.timedelta(days=3, hours=8, minutes=32, seconds=1,
+ microseconds=123): datetime.timedelta(days=3,
+ hours=8,
+ minutes=32,
+ seconds=1,
+ microseconds=123),
3600: datetime.timedelta(hours=1),
}
invalid_inputs = {
- 'abc': ['Duration has wrong format. Use one of these formats instead: [DD] [HH:[MM:]]ss[.uuuuuu].'],
- '3 08:32 01.123': ['Duration has wrong format. Use one of these formats instead: [DD] [HH:[MM:]]ss[.uuuuuu].'],
+ 'abc': [
+ 'Duration has wrong format. Use one of these formats instead: '
+ '[DD] [HH:[MM:]]ss[.uuuuuu].'],
+ '3 08:32 01.123': [
+ 'Duration has wrong format. Use one of these formats instead: '
+ '[DD] [HH:[MM:]]ss[.uuuuuu].'],
}
outputs = {
- datetime.timedelta(days=3, hours=8, minutes=32, seconds=1, microseconds=123): '3 08:32:01.000123',
+ datetime.timedelta(days=3, hours=8, minutes=32, seconds=1,
+ microseconds=123): '3 08:32:01.000123',
}
- field = serializers.DurationField()
+ field = DurationField()
# Choice types...
@@ -1281,7 +1370,7 @@ class TestChoiceField(FieldValues):
'': '',
'amazing': 'amazing',
}
- field = serializers.ChoiceField(
+ field = ChoiceField(
choices=[
('poor', 'Poor quality'),
('medium', 'Medium quality'),
@@ -1293,7 +1382,7 @@ class TestChoiceField(FieldValues):
"""
If `allow_blank=True` then '' is a valid input.
"""
- field = serializers.ChoiceField(
+ field = ChoiceField(
allow_blank=True,
choices=[
('poor', 'Poor quality'),
@@ -1308,7 +1397,7 @@ class TestChoiceField(FieldValues):
"""
If `allow_null=True` then '' on HTML forms is treated as None.
"""
- field = serializers.ChoiceField(
+ field = ChoiceField(
allow_null=True,
choices=[
1, 2, 3
@@ -1324,7 +1413,7 @@ class TestChoiceField(FieldValues):
"""
iter_options() should return a list of options and option groups.
"""
- field = serializers.ChoiceField(
+ field = ChoiceField(
choices=[
('Numbers', ['integer', 'float']),
('Strings', ['text', 'email', 'url']),
@@ -1366,7 +1455,7 @@ class TestChoiceFieldWithType(FieldValues):
'1': 1,
1: 1
}
- field = serializers.ChoiceField(
+ field = ChoiceField(
choices=[
(1, 'Poor quality'),
(2, 'Medium quality'),
@@ -1391,13 +1480,13 @@ class TestChoiceFieldWithListChoices(FieldValues):
outputs = {
'good': 'good'
}
- field = serializers.ChoiceField(choices=('poor', 'medium', 'good'))
+ field = ChoiceField(choices=('poor', 'medium', 'good'))
class TestChoiceFieldWithGroupedChoices(FieldValues):
"""
- Valid and invalid values for a `Choice` field that uses a grouped list for the
- choices, rather than a list of pairs of (`value`, `description`).
+ Valid and invalid values for a `Choice` field that uses a grouped list for
+ the choices, rather than a list of pairs of (`value`, `description`).
"""
valid_inputs = {
'poor': 'poor',
@@ -1410,7 +1499,7 @@ class TestChoiceFieldWithGroupedChoices(FieldValues):
outputs = {
'good': 'good'
}
- field = serializers.ChoiceField(
+ field = ChoiceField(
choices=[
(
'Category',
@@ -1440,7 +1529,7 @@ class TestChoiceFieldWithMixedChoices(FieldValues):
outputs = {
'good': 'good'
}
- field = serializers.ChoiceField(
+ field = ChoiceField(
choices=[
(
'Category',
@@ -1468,9 +1557,10 @@ class TestMultipleChoiceField(FieldValues):
('aircon', 'incorrect'): ['"incorrect" is not a valid choice.']
}
outputs = [
- (['aircon', 'manual', 'incorrect'], set(['aircon', 'manual', 'incorrect']))
+ (['aircon', 'manual', 'incorrect'],
+ set(['aircon', 'manual', 'incorrect']))
]
- field = serializers.MultipleChoiceField(
+ field = MultipleChoiceField(
choices=[
('aircon', 'AirCon'),
('manual', 'Manual drive'),
@@ -1479,7 +1569,7 @@ class TestMultipleChoiceField(FieldValues):
)
def test_against_partial_and_full_updates(self):
- field = serializers.MultipleChoiceField(choices=(('a', 'a'), ('b', 'b')))
+ field = MultipleChoiceField(choices=(('a', 'a'), ('b', 'b')))
field.partial = False
assert field.get_value(QueryDict({})) == []
field.partial = True
@@ -1497,7 +1587,7 @@ class TestEmptyMultipleChoiceField(FieldValues):
)
outputs = [
]
- field = serializers.MultipleChoiceField(
+ field = MultipleChoiceField(
choices=[
('consistency', 'Consistency'),
('availability', 'Availability'),
@@ -1507,7 +1597,7 @@ class TestEmptyMultipleChoiceField(FieldValues):
)
-# File serializers...
+# File ..
class MockFile:
def __init__(self, name='', size=0, url=''):
@@ -1532,16 +1622,20 @@ class TestFileField(FieldValues):
(MockFile(name='example', size=10), MockFile(name='example', size=10))
]
invalid_inputs = [
- ('invalid', ['The submitted data was not a file. Check the encoding type on the form.']),
- (MockFile(name='example.txt', size=0), ['The submitted file is empty.']),
+ ('invalid', [
+ 'The submitted data was not a file. Check the encoding type on '
+ 'the form.']),
+ (MockFile(name='example.txt', size=0),
+ ['The submitted file is empty.']),
(MockFile(name='', size=10), ['No filename could be determined.']),
- (MockFile(name='x' * 100, size=10), ['Ensure this filename has at most 10 characters (it has 100).'])
+ (MockFile(name='x' * 100, size=10),
+ ['Ensure this filename has at most 10 characters (it has 100).'])
]
outputs = [
(MockFile(name='example.txt', url='/example.txt'), '/example.txt'),
('', None)
]
- field = serializers.FileField(max_length=10)
+ field = FileField(max_length=10)
class TestFieldFieldWithName(FieldValues):
@@ -1553,14 +1647,14 @@ class TestFieldFieldWithName(FieldValues):
outputs = [
(MockFile(name='example.txt', url='/example.txt'), 'example.txt')
]
- field = serializers.FileField(use_url=False)
+ field = FileField(use_url=False)
# Stub out mock Django `forms.ImageField` class so we don't *actually*
# call into it's regular validation, or require PIL for testing.
class FailImageValidation(object):
def to_python(self, value):
- raise serializers.ValidationError(self.error_messages['invalid_image'])
+ raise ValidationError(self.error_messages['invalid_image'])
class PassImageValidation(object):
@@ -1574,10 +1668,12 @@ class TestInvalidImageField(FieldValues):
"""
valid_inputs = {}
invalid_inputs = [
- (MockFile(name='example.txt', size=10), ['Upload a valid image. The file you uploaded was either not an image or a corrupted image.'])
+ (MockFile(name='example.txt', size=10), [
+ 'Upload a valid image. The file you uploaded was either not an '
+ 'image or a corrupted image.'])
]
outputs = {}
- field = serializers.ImageField(_DjangoImageField=FailImageValidation)
+ field = ImageField(_DjangoImageField=FailImageValidation)
class TestValidImageField(FieldValues):
@@ -1585,14 +1681,15 @@ class TestValidImageField(FieldValues):
Values for an valid `ImageField`.
"""
valid_inputs = [
- (MockFile(name='example.txt', size=10), MockFile(name='example.txt', size=10))
+ (MockFile(name='example.txt', size=10),
+ MockFile(name='example.txt', size=10))
]
invalid_inputs = {}
outputs = {}
- field = serializers.ImageField(_DjangoImageField=PassImageValidation)
+ field = ImageField(_DjangoImageField=PassImageValidation)
-# Composite serializers...
+# Composite ..
class TestListField(FieldValues):
"""
@@ -1612,24 +1709,26 @@ class TestListField(FieldValues):
([1, 2, 3], [1, 2, 3]),
(['1', '2', '3'], [1, 2, 3])
]
- field = serializers.ListField(child=serializers.IntegerField())
+ field = ListField(child=IntegerField())
def test_no_source_on_child(self):
with pytest.raises(AssertionError) as exc_info:
- serializers.ListField(child=serializers.IntegerField(source='other'))
+ ListField(child=IntegerField(source='other'))
assert str(exc_info.value) == (
- "The `source` argument is not meaningful when applied to a `child=` field. "
+ "The `source` argument is not meaningful when applied to a "
+ "`child=` field. "
"Remove `source=` from the field declaration."
)
def test_collection_types_are_invalid_input(self):
- field = serializers.ListField(child=serializers.CharField())
+ field = ListField(child=CharField())
input_value = ({'one': 'two'})
- with pytest.raises(serializers.ValidationError) as exc_info:
+ with pytest.raises(ValidationError) as exc_info:
field.to_internal_value(input_value)
- assert exc_info.value.detail == ['Expected a list of items but got type "dict".']
+ assert exc_info.value.detail == [
+ 'Expected a list of items but got type "dict".']
class TestEmptyListField(FieldValues):
@@ -1641,7 +1740,7 @@ class TestEmptyListField(FieldValues):
([], ['This list may not be empty.'])
]
outputs = {}
- field = serializers.ListField(child=serializers.IntegerField(), allow_empty=False)
+ field = ListField(child=IntegerField(), allow_empty=False)
class TestUnvalidatedListField(FieldValues):
@@ -1657,7 +1756,7 @@ class TestUnvalidatedListField(FieldValues):
outputs = [
([1, '2', True, [4, 5, 6]], [1, '2', True, [4, 5, 6]]),
]
- field = serializers.ListField()
+ field = ListField()
class TestDictField(FieldValues):
@@ -1674,14 +1773,15 @@ class TestDictField(FieldValues):
outputs = [
({'a': 1, 'b': '2', 3: 3}, {'a': '1', 'b': '2', '3': '3'}),
]
- field = serializers.DictField(child=serializers.CharField())
+ field = DictField(child=CharField())
def test_no_source_on_child(self):
with pytest.raises(AssertionError) as exc_info:
- serializers.DictField(child=serializers.CharField(source='other'))
+ DictField(child=CharField(source='other'))
assert str(exc_info.value) == (
- "The `source` argument is not meaningful when applied to a `child=` field. "
+ "The `source` argument is not meaningful when applied to a "
+ "`child=` field. "
"Remove `source=` from the field declaration."
)
@@ -1689,7 +1789,7 @@ class TestDictField(FieldValues):
"""
If `allow_null=True` then `None` is a valid input.
"""
- field = serializers.DictField(allow_null=True)
+ field = DictField(allow_null=True)
output = field.run_validation(None)
assert output is None
@@ -1706,7 +1806,7 @@ class TestDictFieldWithNullChild(FieldValues):
outputs = [
({'a': None, 'b': '2', 3: 3}, {'a': None, 'b': '2', '3': '3'}),
]
- field = serializers.DictField(child=serializers.CharField(allow_null=True))
+ field = DictField(child=CharField(allow_null=True))
class TestUnvalidatedDictField(FieldValues):
@@ -1722,7 +1822,7 @@ class TestUnvalidatedDictField(FieldValues):
outputs = [
({'a': 1, 'b': [4, 5, 6]}, {'a': 1, 'b': [4, 5, 6]}),
]
- field = serializers.DictField()
+ field = DictField()
class TestJSONField(FieldValues):
@@ -1730,38 +1830,33 @@ class TestJSONField(FieldValues):
Values for `JSONField`.
"""
valid_inputs = [
- ({
- 'a': 1,
- 'b': ['some', 'list', True, 1.23],
- '3': None
- }, {
- 'a': 1,
- 'b': ['some', 'list', True, 1.23],
- '3': None
- }),
+ ({'a': 1,
+ 'b': ['some', 'list', True, 1.23],
+ '3': None},
+ {'a': 1,
+ 'b': ['some', 'list', True, 1.23],
+ '3': None}),
]
invalid_inputs = [
({'a': set()}, ['Value must be valid JSON.']),
]
outputs = [
- ({
- 'a': 1,
- 'b': ['some', 'list', True, 1.23],
- '3': 3
- }, {
- 'a': 1,
- 'b': ['some', 'list', True, 1.23],
- '3': 3
- }),
+ ({'a': 1,
+ 'b': ['some', 'list', True, 1.23],
+ '3': 3},
+ {'a': 1,
+ 'b': ['some', 'list', True, 1.23],
+ '3': 3}),
]
- field = serializers.JSONField()
+ field = JSONField()
def test_html_input_as_json_string(self):
"""
HTML inputs should be treated as a serialized JSON string.
"""
+
class TestSerializer(serializers.Serializer):
- config = serializers.JSONField()
+ config = JSONField()
data = QueryDict(mutable=True)
data.update({'config': '{"a":1}'})
@@ -1787,7 +1882,7 @@ class TestBinaryJSONField(FieldValues):
outputs = [
(['some', 'list', True, 1.23], b'["some", "list", true, 1.23]'),
]
- field = serializers.JSONField(binary=True)
+ field = JSONField(binary=True)
# Tests for FieldField.
@@ -1800,7 +1895,7 @@ class MockRequest:
class TestFileFieldContext:
def test_fully_qualified_when_request_in_context(self):
- field = serializers.FileField(max_length=10)
+ field = FileField(max_length=10)
field._context = {'request': MockRequest()}
obj = MockFile(name='example.txt', url='/example.txt')
value = field.to_representation(obj)
@@ -1813,7 +1908,7 @@ class TestFileFieldContext:
class TestSerializerMethodField:
def test_serializer_method_field(self):
class ExampleSerializer(serializers.Serializer):
- example_field = serializers.SerializerMethodField()
+ example_field = SerializerMethodField()
def get_example_field(self, obj):
return 'ran get_example_field(%d)' % obj['example_field']
@@ -1825,7 +1920,7 @@ class TestSerializerMethodField:
def test_redundant_method_name(self):
class ExampleSerializer(serializers.Serializer):
- example_field = serializers.SerializerMethodField('get_example_field')
+ example_field = SerializerMethodField('get_example_field')
with pytest.raises(AssertionError) as exc_info:
ExampleSerializer().fields
diff --git a/tests/test_generics.py b/tests/test_generics.py
index 247237584..88d3309ad 100644
--- a/tests/test_generics.py
+++ b/tests/test_generics.py
@@ -85,10 +85,8 @@ class TestRootView(TestCase):
for item in items:
BasicModel(text=item).save()
self.objects = BasicModel.objects
- self.data = [
- {'id': obj.id, 'text': obj.text}
- for obj in self.objects.all()
- ]
+ self.data = [{'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()]
self.view = RootView.as_view()
def test_get_root_view(self):
@@ -122,8 +120,10 @@ class TestRootView(TestCase):
request = factory.put('/', data, format='json')
with self.assertNumQueries(0):
response = self.view(request).render()
- self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
- self.assertEqual(response.data, {"detail": 'Method "PUT" not allowed.'})
+ self.assertEqual(response.status_code,
+ status.HTTP_405_METHOD_NOT_ALLOWED)
+ self.assertEqual(response.data,
+ {"detail": 'Method "PUT" not allowed.'})
def test_delete_root_view(self):
"""
@@ -132,8 +132,10 @@ class TestRootView(TestCase):
request = factory.delete('/')
with self.assertNumQueries(0):
response = self.view(request).render()
- self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
- self.assertEqual(response.data, {"detail": 'Method "DELETE" not allowed.'})
+ self.assertEqual(response.status_code,
+ status.HTTP_405_METHOD_NOT_ALLOWED)
+ self.assertEqual(response.data,
+ {"detail": 'Method "DELETE" not allowed.'})
def test_post_cannot_set_id(self):
"""
@@ -156,7 +158,8 @@ class TestRootView(TestCase):
request = factory.post('/', data, HTTP_ACCEPT='text/html')
response = self.view(request).render()
expected_error = 'Ensure this field has no more than 100 characters.'
- self.assertIn(expected_error, response.rendered_content.decode('utf-8'))
+ self.assertIn(expected_error,
+ response.rendered_content.decode('utf-8'))
EXPECTED_QUERIES_FOR_PUT = 2
@@ -171,10 +174,8 @@ class TestInstanceView(TestCase):
for item in items:
BasicModel(text=item).save()
self.objects = BasicModel.objects.exclude(text='filtered out')
- self.data = [
- {'id': obj.id, 'text': obj.text}
- for obj in self.objects.all()
- ]
+ self.data = [{'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()]
self.view = InstanceView.as_view()
self.slug_based_view = SlugBasedInstanceView.as_view()
@@ -196,8 +197,10 @@ class TestInstanceView(TestCase):
request = factory.post('/', data, format='json')
with self.assertNumQueries(0):
response = self.view(request).render()
- self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
- self.assertEqual(response.data, {"detail": 'Method "POST" not allowed.'})
+ self.assertEqual(response.status_code,
+ status.HTTP_405_METHOD_NOT_ALLOWED)
+ self.assertEqual(response.data,
+ {"detail": 'Method "POST" not allowed.'})
def test_put_instance_view(self):
"""
@@ -280,7 +283,8 @@ class TestInstanceView(TestCase):
"""
data = {'text': 'foo'}
filtered_out_pk = BasicModel.objects.filter(text='filtered out')[0].pk
- request = factory.put('/{0}'.format(filtered_out_pk), data, format='json')
+ request = factory.put('/{0}'.format(filtered_out_pk), data,
+ format='json')
response = self.view(request, pk=filtered_out_pk).render()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
@@ -303,7 +307,8 @@ class TestInstanceView(TestCase):
request = factory.put('/', data, HTTP_ACCEPT='text/html')
response = self.view(request, pk=1).render()
expected_error = 'Ensure this field has no more than 100 characters.'
- self.assertIn(expected_error, response.rendered_content.decode('utf-8'))
+ self.assertIn(expected_error,
+ response.rendered_content.decode('utf-8'))
class TestFKInstanceView(TestCase):
@@ -318,10 +323,8 @@ class TestFKInstanceView(TestCase):
ForeignKeySource(name='source_' + item, target=t).save()
self.objects = ForeignKeySource.objects
- self.data = [
- {'id': obj.id, 'name': obj.name}
- for obj in self.objects.all()
- ]
+ self.data = [{'id': obj.id, 'name': obj.name}
+ for obj in self.objects.all()]
self.view = FKInstanceView.as_view()
@@ -339,10 +342,8 @@ class TestOverriddenGetObject(TestCase):
for item in items:
BasicModel(text=item).save()
self.objects = BasicModel.objects
- self.data = [
- {'id': obj.id, 'text': obj.text}
- for obj in self.objects.all()
- ]
+ self.data = [{'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()]
class OverriddenGetObjectView(generics.RetrieveUpdateDestroyAPIView):
"""
@@ -477,10 +478,8 @@ class TestFilterBackendAppliedToViews(TestCase):
for item in items:
BasicModel(text=item).save()
self.objects = BasicModel.objects
- self.data = [
- {'id': obj.id, 'text': obj.text}
- for obj in self.objects.all()
- ]
+ self.data = [{'id': obj.id, 'text': obj.text}
+ for obj in self.objects.all()]
def test_get_root_view_filters_by_name_with_filter_backend(self):
"""
@@ -493,7 +492,8 @@ class TestFilterBackendAppliedToViews(TestCase):
self.assertEqual(len(response.data), 1)
self.assertEqual(response.data, [{'id': 1, 'text': 'foo'}])
- def test_get_root_view_filters_out_all_models_with_exclusive_filter_backend(self):
+ def test_get_root_view_filters_out_all_models_with_exclusive_filter_backend(
+ self):
"""
GET requests to ListCreateAPIView should return empty list when all models are filtered out.
"""
@@ -507,17 +507,20 @@ class TestFilterBackendAppliedToViews(TestCase):
"""
GET requests to RetrieveUpdateDestroyAPIView should raise 404 when model filtered out.
"""
- instance_view = InstanceView.as_view(filter_backends=(ExclusiveFilterBackend,))
+ instance_view = InstanceView.as_view(
+ filter_backends=(ExclusiveFilterBackend,))
request = factory.get('/1')
response = instance_view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
self.assertEqual(response.data, {'detail': 'Not found.'})
- def test_get_instance_view_will_return_single_object_when_filter_does_not_exclude_it(self):
+ def test_get_instance_view_will_return_single_object_when_filter_does_not_exclude_it(
+ self):
"""
GET requests to RetrieveUpdateDestroyAPIView should return a single object when not excluded
"""
- instance_view = InstanceView.as_view(filter_backends=(InclusiveFilterBackend,))
+ instance_view = InstanceView.as_view(
+ filter_backends=(InclusiveFilterBackend,))
request = factory.get('/1')
response = instance_view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
diff --git a/tests/test_metadata.py b/tests/test_metadata.py
index 7a02c2a3d..0e28340a7 100644
--- a/tests/test_metadata.py
+++ b/tests/test_metadata.py
@@ -7,6 +7,10 @@ from django.test import TestCase
from rest_framework import (
exceptions, metadata, serializers, status, versioning, views
)
+from rest_framework.fields import (
+ CharField, ChoiceField, IntegerField, ListField, NullBooleanField
+)
+from rest_framework.relations import PrimaryKeyRelatedField, RelatedField
from rest_framework.renderers import BrowsableAPIRenderer
from rest_framework.request import Request
from rest_framework.test import APIRequestFactory
@@ -21,6 +25,7 @@ class TestMetadata:
"""
OPTIONS requests to views should return a valid 200 response.
"""
+
class ExampleView(views.APIView):
"""Example view."""
pass
@@ -46,8 +51,9 @@ class TestMetadata:
def test_none_metadata(self):
"""
OPTIONS requests to views where `metadata_class = None` should raise
- a MethodNotAllowed exception, which will result in an HTTP 405 response.
+ a MethodNotAllowed exception, which will result in an HTTP 405 response
"""
+
class ExampleView(views.APIView):
metadata_class = None
@@ -61,27 +67,29 @@ class TestMetadata:
On generic views OPTIONS should return an 'actions' key with metadata
on the fields that may be supplied to PUT and POST requests.
"""
+
class NestedField(serializers.Serializer):
- a = serializers.IntegerField()
- b = serializers.IntegerField()
+ a = IntegerField()
+ b = IntegerField()
class ExampleSerializer(serializers.Serializer):
- choice_field = serializers.ChoiceField(['red', 'green', 'blue'])
- integer_field = serializers.IntegerField(
+ choice_field = ChoiceField(['red', 'green', 'blue'])
+ integer_field = IntegerField(
min_value=1, max_value=1000
)
- char_field = serializers.CharField(
+ char_field = CharField(
required=False, min_length=3, max_length=40
)
- list_field = serializers.ListField(
- child=serializers.ListField(
- child=serializers.IntegerField()
+ list_field = ListField(
+ child=ListField(
+ child=IntegerField()
)
)
nested_field = NestedField()
class ExampleView(views.APIView):
"""Example view."""
+
def post(self, request):
pass
@@ -179,13 +187,15 @@ class TestMetadata:
If a user does not have global permissions on an action, then any
metadata associated with it should not be included in OPTION responses.
"""
+
class ExampleSerializer(serializers.Serializer):
- choice_field = serializers.ChoiceField(['red', 'green', 'blue'])
- integer_field = serializers.IntegerField(max_value=10)
- char_field = serializers.CharField(required=False)
+ choice_field = ChoiceField(['red', 'green', 'blue'])
+ integer_field = IntegerField(max_value=10)
+ char_field = CharField(required=False)
class ExampleView(views.APIView):
"""Example view."""
+
def post(self, request):
pass
@@ -209,13 +219,15 @@ class TestMetadata:
If a user does not have object permissions on an action, then any
metadata associated with it should not be included in OPTION responses.
"""
+
class ExampleSerializer(serializers.Serializer):
- choice_field = serializers.ChoiceField(['red', 'green', 'blue'])
- integer_field = serializers.IntegerField(max_value=10)
- char_field = serializers.CharField(required=False)
+ choice_field = ChoiceField(['red', 'green', 'blue'])
+ integer_field = IntegerField(max_value=10)
+ char_field = CharField(required=False)
class ExampleView(views.APIView):
"""Example view."""
+
def post(self, request):
pass
@@ -267,7 +279,7 @@ class TestMetadata:
class TestSimpleMetadataFieldInfo(TestCase):
def test_null_boolean_field_info_type(self):
options = metadata.SimpleMetadata()
- field_info = options.get_field_info(serializers.NullBooleanField())
+ field_info = options.get_field_info(NullBooleanField())
self.assertEqual(field_info['type'], 'boolean')
def test_related_field_choices(self):
@@ -275,7 +287,7 @@ class TestSimpleMetadataFieldInfo(TestCase):
BasicModel.objects.create()
with self.assertNumQueries(0):
field_info = options.get_field_info(
- serializers.RelatedField(queryset=BasicModel.objects.all())
+ RelatedField(queryset=BasicModel.objects.all())
)
self.assertNotIn('choices', field_info)
@@ -287,8 +299,10 @@ class TestModelSerializerMetadata(TestCase):
on the fields that may be supplied to PUT and POST requests. It should
not fail when a read_only PrimaryKeyRelatedField is present
"""
+
class Parent(models.Model):
- integer_field = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(1000)])
+ integer_field = models.IntegerField(
+ validators=[MinValueValidator(1), MaxValueValidator(1000)])
children = models.ManyToManyField('Child')
name = models.CharField(max_length=100, blank=True, null=True)
@@ -296,7 +310,7 @@ class TestModelSerializerMetadata(TestCase):
name = models.CharField(max_length=100)
class ExampleSerializer(serializers.ModelSerializer):
- children = serializers.PrimaryKeyRelatedField(read_only=True, many=True)
+ children = PrimaryKeyRelatedField(read_only=True, many=True)
class Meta:
model = Parent
@@ -304,6 +318,7 @@ class TestModelSerializerMetadata(TestCase):
class ExampleView(views.APIView):
"""Example view."""
+
def post(self, request):
pass
diff --git a/tests/test_multitable_inheritance.py b/tests/test_multitable_inheritance.py
index 611333aa8..0f02dfab6 100644
--- a/tests/test_multitable_inheritance.py
+++ b/tests/test_multitable_inheritance.py
@@ -17,7 +17,8 @@ class ChildModel(ParentModel):
class AssociatedModel(RESTFrameworkModel):
- ref = models.OneToOneField(ParentModel, primary_key=True, on_delete=models.CASCADE)
+ ref = models.OneToOneField(ParentModel, primary_key=True,
+ on_delete=models.CASCADE)
name = models.CharField(max_length=100)
@@ -36,7 +37,6 @@ class AssociatedModelSerializer(serializers.ModelSerializer):
# Tests
class InheritedModelSerializationTests(TestCase):
-
def test_multitable_inherited_model_fields_as_expected(self):
"""
Assert that the parent pointer field is not included in the fields
diff --git a/tests/test_one_to_one_with_inheritance.py b/tests/test_one_to_one_with_inheritance.py
index 06e1cd8b8..fde029dd2 100644
--- a/tests/test_one_to_one_with_inheritance.py
+++ b/tests/test_one_to_one_with_inheritance.py
@@ -5,9 +5,6 @@ from django.test import TestCase
from rest_framework import serializers
from tests.models import RESTFrameworkModel
-
-
-# Models
from tests.test_multitable_inheritance import ChildModel
@@ -26,7 +23,6 @@ class DerivedModelSerializer(serializers.ModelSerializer):
class ChildAssociatedModelSerializer(serializers.ModelSerializer):
-
class Meta:
model = ChildAssociatedModel
fields = ['id', 'child_name']
@@ -34,7 +30,6 @@ class ChildAssociatedModelSerializer(serializers.ModelSerializer):
# Tests
class InheritedModelSerializationTests(TestCase):
-
def test_multitable_inherited_model_fields_as_expected(self):
"""
Assert that the parent pointer field is not included in the fields
diff --git a/tests/test_permissions.py b/tests/test_permissions.py
index f8561e61d..7a4c214e8 100644
--- a/tests/test_permissions.py
+++ b/tests/test_permissions.py
@@ -65,27 +65,33 @@ empty_list_view = EmptyListView.as_view()
def basic_auth_header(username, password):
credentials = ('%s:%s' % (username, password))
- base64_credentials = base64.b64encode(credentials.encode(HTTP_HEADER_ENCODING)).decode(HTTP_HEADER_ENCODING)
+ base64_credentials = base64.b64encode(
+ credentials.encode(HTTP_HEADER_ENCODING)).decode(HTTP_HEADER_ENCODING)
return 'Basic %s' % base64_credentials
class ModelPermissionsIntegrationTests(TestCase):
def setUp(self):
- User.objects.create_user('disallowed', 'disallowed@example.com', 'password')
- user = User.objects.create_user('permitted', 'permitted@example.com', 'password')
+ User.objects.create_user('disallowed', 'disallowed@example.com',
+ 'password')
+ user = User.objects.create_user('permitted', 'permitted@example.com',
+ 'password')
set_many(user, 'user_permissions', [
Permission.objects.get(codename='add_basicmodel'),
Permission.objects.get(codename='change_basicmodel'),
Permission.objects.get(codename='delete_basicmodel')
])
- user = User.objects.create_user('updateonly', 'updateonly@example.com', 'password')
+ user = User.objects.create_user('updateonly', 'updateonly@example.com',
+ 'password')
set_many(user, 'user_permissions', [
Permission.objects.get(codename='change_basicmodel'),
])
self.permitted_credentials = basic_auth_header('permitted', 'password')
- self.disallowed_credentials = basic_auth_header('disallowed', 'password')
- self.updateonly_credentials = basic_auth_header('updateonly', 'password')
+ self.disallowed_credentials = basic_auth_header('disallowed',
+ 'password')
+ self.updateonly_credentials = basic_auth_header('updateonly',
+ 'password')
BasicModel(text='foo').save()
@@ -120,7 +126,8 @@ class ModelPermissionsIntegrationTests(TestCase):
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_has_delete_permissions(self):
- request = factory.delete('/1', HTTP_AUTHORIZATION=self.permitted_credentials)
+ request = factory.delete('/1',
+ HTTP_AUTHORIZATION=self.permitted_credentials)
response = instance_view(request, pk=1)
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
@@ -137,7 +144,8 @@ class ModelPermissionsIntegrationTests(TestCase):
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_does_not_have_delete_permissions(self):
- request = factory.delete('/1', HTTP_AUTHORIZATION=self.disallowed_credentials)
+ request = factory.delete(
+ '/1', HTTP_AUTHORIZATION=self.disallowed_credentials)
response = instance_view(request, pk=1)
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
@@ -196,7 +204,8 @@ class ModelPermissionsIntegrationTests(TestCase):
self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
def test_empty_view_does_not_assert(self):
- request = factory.get('/1', HTTP_AUTHORIZATION=self.permitted_credentials)
+ request = factory.get('/1',
+ HTTP_AUTHORIZATION=self.permitted_credentials)
response = empty_list_view(request, pk=1)
self.assertEqual(response.status_code, status.HTTP_200_OK)
@@ -237,6 +246,7 @@ class ObjectPermissionInstanceView(generics.RetrieveUpdateDestroyAPIView):
authentication_classes = [authentication.BasicAuthentication]
permission_classes = [ViewObjectPermissions]
+
object_permissions_view = ObjectPermissionInstanceView.as_view()
@@ -246,10 +256,12 @@ class ObjectPermissionListView(generics.ListAPIView):
authentication_classes = [authentication.BasicAuthentication]
permission_classes = [ViewObjectPermissions]
+
object_permissions_list_view = ObjectPermissionListView.as_view()
-class GetQuerysetObjectPermissionInstanceView(generics.RetrieveUpdateDestroyAPIView):
+class GetQuerysetObjectPermissionInstanceView(generics.
+ RetrieveUpdateDestroyAPIView):
serializer_class = BasicPermSerializer
authentication_classes = [authentication.BasicAuthentication]
permission_classes = [ViewObjectPermissions]
@@ -258,7 +270,8 @@ class GetQuerysetObjectPermissionInstanceView(generics.RetrieveUpdateDestroyAPIV
return BasicPermModel.objects.all()
-get_queryset_object_permissions_view = GetQuerysetObjectPermissionInstanceView.as_view()
+get_queryset_object_permissions_view = \
+ GetQuerysetObjectPermissionInstanceView.as_view()
@unittest.skipUnless(guardian, 'django-guardian not installed')
@@ -266,16 +279,20 @@ class ObjectPermissionsIntegrationTests(TestCase):
"""
Integration tests for the object level permissions API.
"""
+
def setUp(self):
from guardian.shortcuts import assign_perm
# create users
create = User.objects.create_user
users = {
- 'fullaccess': create('fullaccess', 'fullaccess@example.com', 'password'),
+ 'fullaccess': create('fullaccess', 'fullaccess@example.com',
+ 'password'),
'readonly': create('readonly', 'readonly@example.com', 'password'),
- 'writeonly': create('writeonly', 'writeonly@example.com', 'password'),
- 'deleteonly': create('deleteonly', 'deleteonly@example.com', 'password'),
+ 'writeonly': create('writeonly', 'writeonly@example.com',
+ 'password'),
+ 'deleteonly': create('deleteonly', 'deleteonly@example.com',
+ 'password'),
}
# give everyone model level permissions, as we are not testing those
@@ -310,16 +327,19 @@ class ObjectPermissionsIntegrationTests(TestCase):
self.credentials = {}
for user in users.values():
- self.credentials[user.username] = basic_auth_header(user.username, 'password')
+ self.credentials[user.username] = basic_auth_header(user.username,
+ 'password')
# Delete
def test_can_delete_permissions(self):
- request = factory.delete('/1', HTTP_AUTHORIZATION=self.credentials['deleteonly'])
+ request = factory.delete('/1', HTTP_AUTHORIZATION=self.credentials[
+ 'deleteonly'])
response = object_permissions_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_204_NO_CONTENT)
def test_cannot_delete_permissions(self):
- request = factory.delete('/1', HTTP_AUTHORIZATION=self.credentials['readonly'])
+ request = factory.delete('/1', HTTP_AUTHORIZATION=self.credentials[
+ 'readonly'])
response = object_permissions_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
@@ -351,12 +371,14 @@ class ObjectPermissionsIntegrationTests(TestCase):
# Read
def test_can_read_permissions(self):
- request = factory.get('/1', HTTP_AUTHORIZATION=self.credentials['readonly'])
+ request = factory.get('/1',
+ HTTP_AUTHORIZATION=self.credentials['readonly'])
response = object_permissions_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
def test_cannot_read_permissions(self):
- request = factory.get('/1', HTTP_AUTHORIZATION=self.credentials['writeonly'])
+ request = factory.get('/1',
+ HTTP_AUTHORIZATION=self.credentials['writeonly'])
response = object_permissions_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_404_NOT_FOUND)
@@ -365,21 +387,26 @@ class ObjectPermissionsIntegrationTests(TestCase):
same as ``test_can_read_permissions`` but with a view
that rely on ``.get_queryset()`` instead of ``.queryset``.
"""
- request = factory.get('/1', HTTP_AUTHORIZATION=self.credentials['readonly'])
+ request = factory.get('/1',
+ HTTP_AUTHORIZATION=self.credentials['readonly'])
response = get_queryset_object_permissions_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
# Read list
def test_can_read_list_permissions(self):
- request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['readonly'])
- object_permissions_list_view.cls.filter_backends = (DjangoObjectPermissionsFilter,)
+ request = factory.get('/',
+ HTTP_AUTHORIZATION=self.credentials['readonly'])
+ object_permissions_list_view.cls.filter_backends = (
+ DjangoObjectPermissionsFilter,)
response = object_permissions_list_view(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data[0].get('id'), 1)
def test_cannot_read_list_permissions(self):
- request = factory.get('/', HTTP_AUTHORIZATION=self.credentials['writeonly'])
- object_permissions_list_view.cls.filter_backends = (DjangoObjectPermissionsFilter,)
+ request = factory.get('/',
+ HTTP_AUTHORIZATION=self.credentials['writeonly'])
+ object_permissions_list_view.cls.filter_backends = (
+ DjangoObjectPermissionsFilter,)
response = object_permissions_list_view(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertListEqual(response.data, [])
@@ -429,6 +456,7 @@ class DeniedObjectView(PermissionInstanceView):
class DeniedObjectViewWithDetail(PermissionInstanceView):
permission_classes = (BasicObjectPermWithDetail,)
+
denied_view = DeniedView.as_view()
denied_view_with_detail = DeniedViewWithDetail.as_view()
@@ -441,31 +469,33 @@ denied_object_view_with_detail = DeniedObjectViewWithDetail.as_view()
class CustomPermissionsTests(TestCase):
def setUp(self):
BasicModel(text='foo').save()
- User.objects.create_user('username', 'username@example.com', 'password')
+ User.objects.create_user('username', 'username@example.com',
+ 'password')
credentials = basic_auth_header('username', 'password')
- self.request = factory.get('/1', format='json', HTTP_AUTHORIZATION=credentials)
+ self.request = factory.get('/1', format='json',
+ HTTP_AUTHORIZATION=credentials)
self.custom_message = 'Custom: You cannot access this resource'
def test_permission_denied(self):
- response = denied_view(self.request, pk=1)
- detail = response.data.get('detail')
- self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
- self.assertNotEqual(detail, self.custom_message)
+ response = denied_view(self.request, pk=1)
+ detail = response.data.get('detail')
+ self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+ self.assertNotEqual(detail, self.custom_message)
def test_permission_denied_with_custom_detail(self):
- response = denied_view_with_detail(self.request, pk=1)
- detail = response.data.get('detail')
- self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
- self.assertEqual(detail, self.custom_message)
+ response = denied_view_with_detail(self.request, pk=1)
+ detail = response.data.get('detail')
+ self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+ self.assertEqual(detail, self.custom_message)
def test_permission_denied_for_object(self):
- response = denied_object_view(self.request, pk=1)
- detail = response.data.get('detail')
- self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
- self.assertNotEqual(detail, self.custom_message)
+ response = denied_object_view(self.request, pk=1)
+ detail = response.data.get('detail')
+ self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+ self.assertNotEqual(detail, self.custom_message)
def test_permission_denied_for_object_with_custom_detail(self):
- response = denied_object_view_with_detail(self.request, pk=1)
- detail = response.data.get('detail')
- self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
- self.assertEqual(detail, self.custom_message)
+ response = denied_object_view_with_detail(self.request, pk=1)
+ detail = response.data.get('detail')
+ self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
+ self.assertEqual(detail, self.custom_message)
diff --git a/tests/test_relations.py b/tests/test_relations.py
index a070ad6de..870b90f3a 100644
--- a/tests/test_relations.py
+++ b/tests/test_relations.py
@@ -1,11 +1,14 @@
import uuid
import pytest
-from django.core.exceptions import ImproperlyConfigured
from django.utils.datastructures import MultiValueDict
-from rest_framework import serializers
-from rest_framework.fields import empty
+from rest_framework.fields import UUIDField, ValidationError, empty
+from rest_framework.relations import (
+ Hyperlink, HyperlinkedIdentityField, HyperlinkedRelatedField,
+ ImproperlyConfigured, PrimaryKeyRelatedField, SlugRelatedField,
+ StringRelatedField
+)
from rest_framework.test import APISimpleTestCase
from .utils import (
@@ -16,7 +19,7 @@ from .utils import (
class TestStringRelatedField(APISimpleTestCase):
def setUp(self):
self.instance = MockObject(pk=1, name='foo')
- self.field = serializers.StringRelatedField()
+ self.field = StringRelatedField()
def test_string_related_representation(self):
representation = self.field.to_representation(self.instance)
@@ -31,20 +34,20 @@ class TestPrimaryKeyRelatedField(APISimpleTestCase):
MockObject(pk=3, name='baz')
])
self.instance = self.queryset.items[2]
- self.field = serializers.PrimaryKeyRelatedField(queryset=self.queryset)
+ self.field = PrimaryKeyRelatedField(queryset=self.queryset)
def test_pk_related_lookup_exists(self):
instance = self.field.to_internal_value(self.instance.pk)
assert instance is self.instance
def test_pk_related_lookup_does_not_exist(self):
- with pytest.raises(serializers.ValidationError) as excinfo:
+ with pytest.raises(ValidationError) as excinfo:
self.field.to_internal_value(4)
msg = excinfo.value.detail[0]
assert msg == 'Invalid pk "4" - object does not exist.'
def test_pk_related_lookup_invalid_type(self):
- with pytest.raises(serializers.ValidationError) as excinfo:
+ with pytest.raises(ValidationError) as excinfo:
self.field.to_internal_value(BadType())
msg = excinfo.value.detail[0]
assert msg == 'Incorrect type. Expected pk value, received BadType.'
@@ -54,7 +57,7 @@ class TestPrimaryKeyRelatedField(APISimpleTestCase):
assert representation == self.instance.pk
def test_explicit_many_false(self):
- field = serializers.PrimaryKeyRelatedField(queryset=self.queryset, many=False)
+ field = PrimaryKeyRelatedField(queryset=self.queryset, many=False)
instance = field.to_internal_value(self.instance.pk)
assert instance is self.instance
@@ -67,9 +70,9 @@ class TestProxiedPrimaryKeyRelatedField(APISimpleTestCase):
MockObject(pk=uuid.UUID(int=2), name='baz')
])
self.instance = self.queryset.items[2]
- self.field = serializers.PrimaryKeyRelatedField(
+ self.field = PrimaryKeyRelatedField(
queryset=self.queryset,
- pk_field=serializers.UUIDField(format='int')
+ pk_field=UUIDField(format='int')
)
def test_pk_related_lookup_exists(self):
@@ -77,7 +80,7 @@ class TestProxiedPrimaryKeyRelatedField(APISimpleTestCase):
assert instance is self.instance
def test_pk_related_lookup_does_not_exist(self):
- with pytest.raises(serializers.ValidationError) as excinfo:
+ with pytest.raises(ValidationError) as excinfo:
self.field.to_internal_value(4)
msg = excinfo.value.detail[0]
assert msg == 'Invalid pk "00000000-0000-0000-0000-000000000004" - object does not exist.'
@@ -89,7 +92,7 @@ class TestProxiedPrimaryKeyRelatedField(APISimpleTestCase):
class TestHyperlinkedRelatedField(APISimpleTestCase):
def setUp(self):
- self.field = serializers.HyperlinkedRelatedField(
+ self.field = HyperlinkedRelatedField(
view_name='example', read_only=True)
self.field.reverse = mock_reverse
self.field._context = {'request': True}
@@ -102,7 +105,7 @@ class TestHyperlinkedRelatedField(APISimpleTestCase):
class TestHyperlinkedIdentityField(APISimpleTestCase):
def setUp(self):
self.instance = MockObject(pk=1, name='foo')
- self.field = serializers.HyperlinkedIdentityField(view_name='example')
+ self.field = HyperlinkedIdentityField(view_name='example')
self.field.reverse = mock_reverse
self.field._context = {'request': True}
@@ -135,14 +138,15 @@ class TestHyperlinkedIdentityFieldWithFormat(APISimpleTestCase):
Tests for a hyperlinked identity field that has a `format` set,
which enforces that alternate formats are never linked too.
- Eg. If your API includes some endpoints that accept both `.xml` and `.json`,
- but other endpoints that only accept `.json`, we allow for hyperlinked
+ Eg. If your API includes some endpoints that accept both `.xml` and `.json`
+ but other endpoints only accept `.json`, we allow for hyperlinked
relationships that enforce only a single suffix type.
"""
def setUp(self):
self.instance = MockObject(pk=1, name='foo')
- self.field = serializers.HyperlinkedIdentityField(view_name='example', format='json')
+ self.field = HyperlinkedIdentityField(view_name='example',
+ format='json')
self.field.reverse = mock_reverse
self.field._context = {'request': True}
@@ -164,7 +168,7 @@ class TestSlugRelatedField(APISimpleTestCase):
MockObject(pk=3, name='baz')
])
self.instance = self.queryset.items[2]
- self.field = serializers.SlugRelatedField(
+ self.field = SlugRelatedField(
slug_field='name', queryset=self.queryset
)
@@ -173,13 +177,13 @@ class TestSlugRelatedField(APISimpleTestCase):
assert instance is self.instance
def test_slug_related_lookup_does_not_exist(self):
- with pytest.raises(serializers.ValidationError) as excinfo:
+ with pytest.raises(ValidationError) as excinfo:
self.field.to_internal_value('doesnotexist')
msg = excinfo.value.detail[0]
assert msg == 'Object with name=doesnotexist does not exist.'
def test_slug_related_lookup_invalid_type(self):
- with pytest.raises(serializers.ValidationError) as excinfo:
+ with pytest.raises(ValidationError) as excinfo:
self.field.to_internal_value(BadType())
msg = excinfo.value.detail[0]
assert msg == 'Invalid value.'
@@ -191,7 +195,7 @@ class TestSlugRelatedField(APISimpleTestCase):
def test_overriding_get_queryset(self):
qs = self.queryset
- class NoQuerySetSlugRelatedField(serializers.SlugRelatedField):
+ class NoQuerySetSlugRelatedField(SlugRelatedField):
def get_queryset(self):
return qs
@@ -202,7 +206,7 @@ class TestSlugRelatedField(APISimpleTestCase):
class TestManyRelatedField(APISimpleTestCase):
def setUp(self):
self.instance = MockObject(pk=1, name='foo')
- self.field = serializers.StringRelatedField(many=True)
+ self.field = StringRelatedField(many=True)
self.field.field_name = 'foo'
def test_get_value_regular_dictionary_full(self):
@@ -232,7 +236,7 @@ class TestManyRelatedField(APISimpleTestCase):
class TestHyperlink:
def setup(self):
- self.default_hyperlink = serializers.Hyperlink('http://example.com', 'test')
+ self.default_hyperlink = Hyperlink('http://example.com', 'test')
def test_can_be_pickled(self):
import pickle
diff --git a/tests/test_relations_generic.py b/tests/test_relations_generic.py
index babc2269c..126ddd425 100644
--- a/tests/test_relations_generic.py
+++ b/tests/test_relations_generic.py
@@ -9,6 +9,7 @@ from django.test import TestCase
from django.utils.encoding import python_2_unicode_compatible
from rest_framework import serializers
+from rest_framework.relations import StringRelatedField
@python_2_unicode_compatible
@@ -51,7 +52,8 @@ class Note(models.Model):
class TestGenericRelations(TestCase):
def setUp(self):
- self.bookmark = Bookmark.objects.create(url='https://www.djangoproject.com/')
+ self.bookmark = Bookmark.objects.create(
+ url='https://www.djangoproject.com/')
Tag.objects.create(tagged_item=self.bookmark, tag='django')
Tag.objects.create(tagged_item=self.bookmark, tag='python')
self.note = Note.objects.create(text='Remember the milk')
@@ -64,7 +66,7 @@ class TestGenericRelations(TestCase):
"""
class BookmarkSerializer(serializers.ModelSerializer):
- tags = serializers.StringRelatedField(many=True)
+ tags = StringRelatedField(many=True)
class Meta:
model = Bookmark
@@ -84,7 +86,7 @@ class TestGenericRelations(TestCase):
"""
class TagSerializer(serializers.ModelSerializer):
- tagged_item = serializers.StringRelatedField()
+ tagged_item = StringRelatedField()
class Meta:
model = Tag
diff --git a/tests/test_relations_hyperlink.py b/tests/test_relations_hyperlink.py
index cc74debb3..f5706a2fb 100644
--- a/tests/test_relations_hyperlink.py
+++ b/tests/test_relations_hyperlink.py
@@ -11,7 +11,8 @@ from tests.models import (
)
factory = APIRequestFactory()
-request = factory.get('/') # Just to ensure we have a request in the serializer context
+request = factory.get(
+ '/') # Just to ensure we have a request in the serializer context
def dummy_view(request, pk):
@@ -20,13 +21,20 @@ def dummy_view(request, pk):
urlpatterns = [
url(r'^dummyurl/(?P[0-9]+)/$', dummy_view, name='dummy-url'),
- url(r'^manytomanysource/(?P[0-9]+)/$', dummy_view, name='manytomanysource-detail'),
- url(r'^manytomanytarget/(?P[0-9]+)/$', dummy_view, name='manytomanytarget-detail'),
- url(r'^foreignkeysource/(?P[0-9]+)/$', dummy_view, name='foreignkeysource-detail'),
- url(r'^foreignkeytarget/(?P[0-9]+)/$', dummy_view, name='foreignkeytarget-detail'),
- url(r'^nullableforeignkeysource/(?P[0-9]+)/$', dummy_view, name='nullableforeignkeysource-detail'),
- url(r'^onetoonetarget/(?P[0-9]+)/$', dummy_view, name='onetoonetarget-detail'),
- url(r'^nullableonetoonesource/(?P[0-9]+)/$', dummy_view, name='nullableonetoonesource-detail'),
+ url(r'^manytomanysource/(?P[0-9]+)/$', dummy_view,
+ name='manytomanysource-detail'),
+ url(r'^manytomanytarget/(?P[0-9]+)/$', dummy_view,
+ name='manytomanytarget-detail'),
+ url(r'^foreignkeysource/(?P[0-9]+)/$', dummy_view,
+ name='foreignkeysource-detail'),
+ url(r'^foreignkeytarget/(?P[0-9]+)/$', dummy_view,
+ name='foreignkeytarget-detail'),
+ url(r'^nullableforeignkeysource/(?P[0-9]+)/$', dummy_view,
+ name='nullableforeignkeysource-detail'),
+ url(r'^onetoonetarget/(?P[0-9]+)/$', dummy_view,
+ name='onetoonetarget-detail'),
+ url(r'^nullableonetoonesource/(?P[0-9]+)/$', dummy_view,
+ name='nullableonetoonesource-detail'),
]
@@ -57,7 +65,8 @@ class ForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
# Nullable ForeignKey
-class NullableForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
+class NullableForeignKeySourceSerializer(serializers.
+ HyperlinkedModelSerializer):
class Meta:
model = NullableForeignKeySource
fields = ('url', 'name', 'target')
@@ -84,83 +93,141 @@ class HyperlinkedManyToManyTests(TestCase):
def test_relative_hyperlinks(self):
queryset = ManyToManySource.objects.all()
- serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': None})
+ serializer = ManyToManySourceSerializer(queryset, many=True,
+ context={'request': None})
expected = [
- {'url': '/manytomanysource/1/', 'name': 'source-1', 'targets': ['/manytomanytarget/1/']},
- {'url': '/manytomanysource/2/', 'name': 'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']},
- {'url': '/manytomanysource/3/', 'name': 'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}
+ {'url': '/manytomanysource/1/', 'name': 'source-1',
+ 'targets': ['/manytomanytarget/1/']},
+ {'url': '/manytomanysource/2/', 'name': 'source-2',
+ 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']},
+ {'url': '/manytomanysource/3/', 'name': 'source-3',
+ 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/',
+ '/manytomanytarget/3/']}
]
with self.assertNumQueries(4):
self.assertEqual(serializer.data, expected)
def test_many_to_many_retrieve(self):
queryset = ManyToManySource.objects.all()
- serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = ManyToManySourceSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']},
- {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
- {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
+ {'url': 'http://testserver/manytomanysource/1/',
+ 'name': 'source-1',
+ 'targets': ['http://testserver/manytomanytarget/1/']},
+ {'url': 'http://testserver/manytomanysource/2/',
+ 'name': 'source-2',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/2/']},
+ {'url': 'http://testserver/manytomanysource/3/',
+ 'name': 'source-3',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/2/',
+ 'http://testserver/manytomanytarget/3/']}
]
with self.assertNumQueries(4):
self.assertEqual(serializer.data, expected)
def test_many_to_many_retrieve_prefetch_related(self):
queryset = ManyToManySource.objects.all().prefetch_related('targets')
- serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = ManyToManySourceSerializer(queryset, many=True,
+ context={'request': request})
with self.assertNumQueries(2):
serializer.data
def test_reverse_many_to_many_retrieve(self):
queryset = ManyToManyTarget.objects.all()
- serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
+ serializer = ManyToManyTargetSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
- {'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
- {'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']}
+ {'url': 'http://testserver/manytomanytarget/1/',
+ 'name': 'target-1',
+ 'sources': ['http://testserver/manytomanysource/1/',
+ 'http://testserver/manytomanysource/2/',
+ 'http://testserver/manytomanysource/3/']},
+ {'url': 'http://testserver/manytomanytarget/2/',
+ 'name': 'target-2',
+ 'sources': ['http://testserver/manytomanysource/2/',
+ 'http://testserver/manytomanysource/3/']},
+ {'url': 'http://testserver/manytomanytarget/3/',
+ 'name': 'target-3',
+ 'sources': ['http://testserver/manytomanysource/3/']}
]
with self.assertNumQueries(4):
self.assertEqual(serializer.data, expected)
def test_many_to_many_update(self):
- data = {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
+ data = {'url': 'http://testserver/manytomanysource/1/',
+ 'name': 'source-1',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/2/',
+ 'http://testserver/manytomanytarget/3/']}
instance = ManyToManySource.objects.get(pk=1)
- serializer = ManyToManySourceSerializer(instance, data=data, context={'request': request})
+ serializer = ManyToManySourceSerializer(instance, data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = ManyToManySource.objects.all()
- serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = ManyToManySourceSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']},
- {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
- {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
+ {'url': 'http://testserver/manytomanysource/1/',
+ 'name': 'source-1',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/2/',
+ 'http://testserver/manytomanytarget/3/']},
+ {'url': 'http://testserver/manytomanysource/2/',
+ 'name': 'source-2',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/2/']},
+ {'url': 'http://testserver/manytomanysource/3/',
+ 'name': 'source-3',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/2/',
+ 'http://testserver/manytomanytarget/3/']}
]
self.assertEqual(serializer.data, expected)
def test_reverse_many_to_many_update(self):
- data = {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/']}
+ data = {'url': 'http://testserver/manytomanytarget/1/',
+ 'name': 'target-1',
+ 'sources': ['http://testserver/manytomanysource/1/']}
instance = ManyToManyTarget.objects.get(pk=1)
- serializer = ManyToManyTargetSerializer(instance, data=data, context={'request': request})
+ serializer = ManyToManyTargetSerializer(instance, data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure target 1 is updated, and everything else is as expected
queryset = ManyToManyTarget.objects.all()
- serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
+ serializer = ManyToManyTargetSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/']},
- {'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
- {'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']}
+ {'url': 'http://testserver/manytomanytarget/1/',
+ 'name': 'target-1',
+ 'sources': ['http://testserver/manytomanysource/1/']},
+ {'url': 'http://testserver/manytomanytarget/2/',
+ 'name': 'target-2',
+ 'sources': ['http://testserver/manytomanysource/2/',
+ 'http://testserver/manytomanysource/3/']},
+ {'url': 'http://testserver/manytomanytarget/3/',
+ 'name': 'target-3',
+ 'sources': ['http://testserver/manytomanysource/3/']}
]
self.assertEqual(serializer.data, expected)
def test_many_to_many_create(self):
- data = {'url': 'http://testserver/manytomanysource/4/', 'name': 'source-4', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/3/']}
- serializer = ManyToManySourceSerializer(data=data, context={'request': request})
+ data = {'url': 'http://testserver/manytomanysource/4/',
+ 'name': 'source-4',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/3/']}
+ serializer = ManyToManySourceSerializer(data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
@@ -168,18 +235,35 @@ class HyperlinkedManyToManyTests(TestCase):
# Ensure source 4 is added, and everything else is as expected
queryset = ManyToManySource.objects.all()
- serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = ManyToManySourceSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']},
- {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
- {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']},
- {'url': 'http://testserver/manytomanysource/4/', 'name': 'source-4', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/3/']}
+ {'url': 'http://testserver/manytomanysource/1/',
+ 'name': 'source-1',
+ 'targets': ['http://testserver/manytomanytarget/1/']},
+ {'url': 'http://testserver/manytomanysource/2/',
+ 'name': 'source-2',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/2/']},
+ {'url': 'http://testserver/manytomanysource/3/',
+ 'name': 'source-3',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/2/',
+ 'http://testserver/manytomanytarget/3/']},
+ {'url': 'http://testserver/manytomanysource/4/',
+ 'name': 'source-4',
+ 'targets': ['http://testserver/manytomanytarget/1/',
+ 'http://testserver/manytomanytarget/3/']}
]
self.assertEqual(serializer.data, expected)
def test_reverse_many_to_many_create(self):
- data = {'url': 'http://testserver/manytomanytarget/4/', 'name': 'target-4', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/3/']}
- serializer = ManyToManyTargetSerializer(data=data, context={'request': request})
+ data = {'url': 'http://testserver/manytomanytarget/4/',
+ 'name': 'target-4',
+ 'sources': ['http://testserver/manytomanysource/1/',
+ 'http://testserver/manytomanysource/3/']}
+ serializer = ManyToManyTargetSerializer(data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
@@ -187,12 +271,25 @@ class HyperlinkedManyToManyTests(TestCase):
# Ensure target 4 is added, and everything else is as expected
queryset = ManyToManyTarget.objects.all()
- serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
+ serializer = ManyToManyTargetSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
- {'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
- {'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']},
- {'url': 'http://testserver/manytomanytarget/4/', 'name': 'target-4', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/3/']}
+ {'url': 'http://testserver/manytomanytarget/1/',
+ 'name': 'target-1',
+ 'sources': ['http://testserver/manytomanysource/1/',
+ 'http://testserver/manytomanysource/2/',
+ 'http://testserver/manytomanysource/3/']},
+ {'url': 'http://testserver/manytomanytarget/2/',
+ 'name': 'target-2',
+ 'sources': ['http://testserver/manytomanysource/2/',
+ 'http://testserver/manytomanysource/3/']},
+ {'url': 'http://testserver/manytomanytarget/3/',
+ 'name': 'target-3',
+ 'sources': ['http://testserver/manytomanysource/3/']},
+ {'url': 'http://testserver/manytomanytarget/4/',
+ 'name': 'target-4',
+ 'sources': ['http://testserver/manytomanysource/1/',
+ 'http://testserver/manytomanysource/3/']}
]
self.assertEqual(serializer.data, expected)
@@ -210,62 +307,99 @@ class HyperlinkedForeignKeyTests(TestCase):
def test_foreign_key_retrieve(self):
queryset = ForeignKeySource.objects.all()
- serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = ForeignKeySourceSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'}
+ {'url': 'http://testserver/foreignkeysource/1/',
+ 'name': 'source-1',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/foreignkeysource/2/',
+ 'name': 'source-2',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/foreignkeysource/3/',
+ 'name': 'source-3',
+ 'target': 'http://testserver/foreignkeytarget/1/'}
]
with self.assertNumQueries(1):
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_retrieve(self):
queryset = ForeignKeyTarget.objects.all()
- serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
+ serializer = ForeignKeyTargetSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/2/', 'http://testserver/foreignkeysource/3/']},
- {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
+ {'url': 'http://testserver/foreignkeytarget/1/',
+ 'name': 'target-1',
+ 'sources': ['http://testserver/foreignkeysource/1/',
+ 'http://testserver/foreignkeysource/2/',
+ 'http://testserver/foreignkeysource/3/']},
+ {'url': 'http://testserver/foreignkeytarget/2/',
+ 'name': 'target-2', 'sources': []},
]
with self.assertNumQueries(3):
self.assertEqual(serializer.data, expected)
def test_foreign_key_update(self):
- data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/2/'}
+ data = {'url': 'http://testserver/foreignkeysource/1/',
+ 'name': 'source-1',
+ 'target': 'http://testserver/foreignkeytarget/2/'}
instance = ForeignKeySource.objects.get(pk=1)
- serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
+ serializer = ForeignKeySourceSerializer(instance, data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
- serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = ForeignKeySourceSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/2/'},
- {'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'}
+ {'url': 'http://testserver/foreignkeysource/1/',
+ 'name': 'source-1',
+ 'target': 'http://testserver/foreignkeytarget/2/'},
+ {'url': 'http://testserver/foreignkeysource/2/',
+ 'name': 'source-2',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/foreignkeysource/3/',
+ 'name': 'source-3',
+ 'target': 'http://testserver/foreignkeytarget/1/'}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_incorrect_type(self):
- data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 2}
+ data = {'url': 'http://testserver/foreignkeysource/1/',
+ 'name': 'source-1', 'target': 2}
instance = ForeignKeySource.objects.get(pk=1)
- serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
+ serializer = ForeignKeySourceSerializer(instance, data=data,
+ context={'request': request})
self.assertFalse(serializer.is_valid())
- self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected URL string, received int.']})
+ self.assertEqual(serializer.errors, {
+ 'target': ['Incorrect type. Expected URL string, received int.']})
def test_reverse_foreign_key_update(self):
- data = {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']}
+ data = {'url': 'http://testserver/foreignkeytarget/2/',
+ 'name': 'target-2',
+ 'sources': ['http://testserver/foreignkeysource/1/',
+ 'http://testserver/foreignkeysource/3/']}
instance = ForeignKeyTarget.objects.get(pk=2)
- serializer = ForeignKeyTargetSerializer(instance, data=data, context={'request': request})
+ serializer = ForeignKeyTargetSerializer(instance, data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
# We shouldn't have saved anything to the db yet since save
# hasn't been called.
queryset = ForeignKeyTarget.objects.all()
- new_serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
+ new_serializer = ForeignKeyTargetSerializer(queryset, many=True,
+ context={
+ 'request': request})
expected = [
- {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/2/', 'http://testserver/foreignkeysource/3/']},
- {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
+ {'url': 'http://testserver/foreignkeytarget/1/',
+ 'name': 'target-1',
+ 'sources': ['http://testserver/foreignkeysource/1/',
+ 'http://testserver/foreignkeysource/2/',
+ 'http://testserver/foreignkeysource/3/']},
+ {'url': 'http://testserver/foreignkeytarget/2/',
+ 'name': 'target-2', 'sources': []},
]
self.assertEqual(new_serializer.data, expected)
@@ -274,16 +408,25 @@ class HyperlinkedForeignKeyTests(TestCase):
# Ensure target 2 is update, and everything else is as expected
queryset = ForeignKeyTarget.objects.all()
- serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
+ serializer = ForeignKeyTargetSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/2/']},
- {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']},
+ {'url': 'http://testserver/foreignkeytarget/1/',
+ 'name': 'target-1',
+ 'sources': ['http://testserver/foreignkeysource/2/']},
+ {'url': 'http://testserver/foreignkeytarget/2/',
+ 'name': 'target-2',
+ 'sources': ['http://testserver/foreignkeysource/1/',
+ 'http://testserver/foreignkeysource/3/']},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create(self):
- data = {'url': 'http://testserver/foreignkeysource/4/', 'name': 'source-4', 'target': 'http://testserver/foreignkeytarget/2/'}
- serializer = ForeignKeySourceSerializer(data=data, context={'request': request})
+ data = {'url': 'http://testserver/foreignkeysource/4/',
+ 'name': 'source-4',
+ 'target': 'http://testserver/foreignkeytarget/2/'}
+ serializer = ForeignKeySourceSerializer(data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
@@ -291,18 +434,31 @@ class HyperlinkedForeignKeyTests(TestCase):
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
- serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = ForeignKeySourceSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/foreignkeysource/4/', 'name': 'source-4', 'target': 'http://testserver/foreignkeytarget/2/'},
+ {'url': 'http://testserver/foreignkeysource/1/',
+ 'name': 'source-1',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/foreignkeysource/2/',
+ 'name': 'source-2',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/foreignkeysource/3/',
+ 'name': 'source-3',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/foreignkeysource/4/',
+ 'name': 'source-4',
+ 'target': 'http://testserver/foreignkeytarget/2/'},
]
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_create(self):
- data = {'url': 'http://testserver/foreignkeytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']}
- serializer = ForeignKeyTargetSerializer(data=data, context={'request': request})
+ data = {'url': 'http://testserver/foreignkeytarget/3/',
+ 'name': 'target-3',
+ 'sources': ['http://testserver/foreignkeysource/1/',
+ 'http://testserver/foreignkeysource/3/']}
+ serializer = ForeignKeyTargetSerializer(data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
@@ -310,20 +466,30 @@ class HyperlinkedForeignKeyTests(TestCase):
# Ensure target 4 is added, and everything else is as expected
queryset = ForeignKeyTarget.objects.all()
- serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
+ serializer = ForeignKeyTargetSerializer(queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/2/']},
- {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
- {'url': 'http://testserver/foreignkeytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']},
+ {'url': 'http://testserver/foreignkeytarget/1/',
+ 'name': 'target-1',
+ 'sources': ['http://testserver/foreignkeysource/2/']},
+ {'url': 'http://testserver/foreignkeytarget/2/',
+ 'name': 'target-2', 'sources': []},
+ {'url': 'http://testserver/foreignkeytarget/3/',
+ 'name': 'target-3',
+ 'sources': ['http://testserver/foreignkeysource/1/',
+ 'http://testserver/foreignkeysource/3/']},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_invalid_null(self):
- data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': None}
+ data = {'url': 'http://testserver/foreignkeysource/1/',
+ 'name': 'source-1', 'target': None}
instance = ForeignKeySource.objects.get(pk=1)
- serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
+ serializer = ForeignKeySourceSerializer(instance, data=data,
+ context={'request': request})
self.assertFalse(serializer.is_valid())
- self.assertEqual(serializer.errors, {'target': ['This field may not be null.']})
+ self.assertEqual(serializer.errors,
+ {'target': ['This field may not be null.']})
@override_settings(ROOT_URLCONF='tests.test_relations_hyperlink')
@@ -334,22 +500,32 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
for idx in range(1, 4):
if idx == 3:
target = None
- source = NullableForeignKeySource(name='source-%d' % idx, target=target)
+ source = NullableForeignKeySource(name='source-%d' % idx,
+ target=target)
source.save()
def test_foreign_key_retrieve_with_null(self):
queryset = NullableForeignKeySource.objects.all()
- serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = NullableForeignKeySourceSerializer(
+ queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
+ {'url': 'http://testserver/nullableforeignkeysource/1/',
+ 'name': 'source-1',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/nullableforeignkeysource/2/',
+ 'name': 'source-2',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/nullableforeignkeysource/3/',
+ 'name': 'source-3', 'target': None},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create_with_valid_null(self):
- data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
- serializer = NullableForeignKeySourceSerializer(data=data, context={'request': request})
+ data = {'url': 'http://testserver/nullableforeignkeysource/4/',
+ 'name': 'source-4', 'target': None}
+ serializer = NullableForeignKeySourceSerializer(data=data, context={
+ 'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
@@ -357,12 +533,20 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
# Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
- serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = NullableForeignKeySourceSerializer(
+ queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
- {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
+ {'url': 'http://testserver/nullableforeignkeysource/1/',
+ 'name': 'source-1',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/nullableforeignkeysource/2/',
+ 'name': 'source-2',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/nullableforeignkeysource/3/',
+ 'name': 'source-3', 'target': None},
+ {'url': 'http://testserver/nullableforeignkeysource/4/',
+ 'name': 'source-4', 'target': None}
]
self.assertEqual(serializer.data, expected)
@@ -371,9 +555,13 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
The emptystring should be interpreted as null in the context
of relationships.
"""
- data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': ''}
- expected_data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
- serializer = NullableForeignKeySourceSerializer(data=data, context={'request': request})
+ data = {'url': 'http://testserver/nullableforeignkeysource/4/',
+ 'name': 'source-4', 'target': ''}
+ expected_data = {
+ 'url': 'http://testserver/nullableforeignkeysource/4/',
+ 'name': 'source-4', 'target': None}
+ serializer = NullableForeignKeySourceSerializer(data=data, context={
+ 'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, expected_data)
@@ -381,30 +569,47 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
# Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
- serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = NullableForeignKeySourceSerializer(
+ queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
- {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
+ {'url': 'http://testserver/nullableforeignkeysource/1/',
+ 'name': 'source-1',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/nullableforeignkeysource/2/',
+ 'name': 'source-2',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/nullableforeignkeysource/3/',
+ 'name': 'source-3', 'target': None},
+ {'url': 'http://testserver/nullableforeignkeysource/4/',
+ 'name': 'source-4', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_valid_null(self):
- data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}
+ data = {'url': 'http://testserver/nullableforeignkeysource/1/',
+ 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1)
- serializer = NullableForeignKeySourceSerializer(instance, data=data, context={'request': request})
+ serializer = NullableForeignKeySourceSerializer(
+ instance, data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
- serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = NullableForeignKeySourceSerializer(
+ queryset, many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None},
- {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
+ {'url': 'http://testserver/nullableforeignkeysource/1/',
+ 'name': 'source-1', 'target': None},
+ {'url': 'http://testserver/nullableforeignkeysource/2/',
+ 'name': 'source-2',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/nullableforeignkeysource/3/',
+ 'name': 'source-3', 'target': None},
]
self.assertEqual(serializer.data, expected)
@@ -413,21 +618,33 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
The emptystring should be interpreted as null in the context
of relationships.
"""
- data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': ''}
- expected_data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}
+ data = {'url': 'http://testserver/nullableforeignkeysource/1/',
+ 'name': 'source-1', 'target': ''}
+ expected_data = {
+ 'url': 'http://testserver/nullableforeignkeysource/1/',
+ 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1)
- serializer = NullableForeignKeySourceSerializer(instance, data=data, context={'request': request})
+ serializer = NullableForeignKeySourceSerializer(
+ instance, data=data,
+ context={'request': request})
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, expected_data)
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
- serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
+ serializer = NullableForeignKeySourceSerializer(
+ queryset,
+ many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None},
- {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
- {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
+ {'url': 'http://testserver/nullableforeignkeysource/1/',
+ 'name': 'source-1', 'target': None},
+ {'url': 'http://testserver/nullableforeignkeysource/2/',
+ 'name': 'source-2',
+ 'target': 'http://testserver/foreignkeytarget/1/'},
+ {'url': 'http://testserver/nullableforeignkeysource/3/',
+ 'name': 'source-3', 'target': None},
]
self.assertEqual(serializer.data, expected)
@@ -444,9 +661,14 @@ class HyperlinkedNullableOneToOneTests(TestCase):
def test_reverse_foreign_key_retrieve_with_null(self):
queryset = OneToOneTarget.objects.all()
- serializer = NullableOneToOneTargetSerializer(queryset, many=True, context={'request': request})
+ serializer = NullableOneToOneTargetSerializer(
+ queryset,
+ many=True,
+ context={'request': request})
expected = [
- {'url': 'http://testserver/onetoonetarget/1/', 'name': 'target-1', 'nullable_source': 'http://testserver/nullableonetoonesource/1/'},
- {'url': 'http://testserver/onetoonetarget/2/', 'name': 'target-2', 'nullable_source': None},
+ {'url': 'http://testserver/onetoonetarget/1/', 'name': 'target-1',
+ 'nullable_source': 'http://testserver/nullableonetoonesource/1/'},
+ {'url': 'http://testserver/onetoonetarget/2/', 'name': 'target-2',
+ 'nullable_source': None},
]
self.assertEqual(serializer.data, expected)
diff --git a/tests/test_relations_pk.py b/tests/test_relations_pk.py
index 7a3d45927..fbd5ee358 100644
--- a/tests/test_relations_pk.py
+++ b/tests/test_relations_pk.py
@@ -248,7 +248,8 @@ class PKForeignKeyTests(TestCase):
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid())
- self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]})
+ self.assertEqual(serializer.errors, {'target': [
+ 'Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]})
def test_reverse_foreign_key_update(self):
data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]}
@@ -319,7 +320,8 @@ class PKForeignKeyTests(TestCase):
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid())
- self.assertEqual(serializer.errors, {'target': ['This field may not be null.']})
+ self.assertEqual(serializer.errors,
+ {'target': ['This field may not be null.']})
def test_foreign_key_with_unsaved(self):
source = ForeignKeySource(name='source-unsaved')
@@ -345,9 +347,11 @@ class PKForeignKeyTests(TestCase):
Let's say we wanted to fill the non-nullable model field inside
Model.save(), we would make it empty and not required.
"""
+
class ModelSerializer(ForeignKeySourceSerializer):
class Meta(ForeignKeySourceSerializer.Meta):
extra_kwargs = {'target': {'required': False}}
+
serializer = ModelSerializer(data={'name': 'test'})
serializer.is_valid(raise_exception=True)
self.assertNotIn('target', serializer.validated_data)
@@ -360,7 +364,8 @@ class PKNullableForeignKeyTests(TestCase):
for idx in range(1, 4):
if idx == 3:
target = None
- source = NullableForeignKeySource(name='source-%d' % idx, target=target)
+ source = NullableForeignKeySource(name='source-%d' % idx,
+ target=target)
source.save()
def test_foreign_key_retrieve_with_null(self):
diff --git a/tests/test_relations_slug.py b/tests/test_relations_slug.py
index 1e1bdaa62..3e22e6973 100644
--- a/tests/test_relations_slug.py
+++ b/tests/test_relations_slug.py
@@ -73,7 +73,8 @@ class SlugForeignKeyTests(TestCase):
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
- {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']},
+ {'id': 1, 'name': 'target-1',
+ 'sources': ['source-1', 'source-2', 'source-3']},
{'id': 2, 'name': 'target-2', 'sources': []},
]
self.assertEqual(serializer.data, expected)
@@ -107,10 +108,12 @@ class SlugForeignKeyTests(TestCase):
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid())
- self.assertEqual(serializer.errors, {'target': ['Object with name=123 does not exist.']})
+ self.assertEqual(serializer.errors,
+ {'target': ['Object with name=123 does not exist.']})
def test_reverse_foreign_key_update(self):
- data = {'id': 2, 'name': 'target-2', 'sources': ['source-1', 'source-3']}
+ data = {'id': 2, 'name': 'target-2',
+ 'sources': ['source-1', 'source-3']}
instance = ForeignKeyTarget.objects.get(pk=2)
serializer = ForeignKeyTargetSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
@@ -119,7 +122,8 @@ class SlugForeignKeyTests(TestCase):
queryset = ForeignKeyTarget.objects.all()
new_serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
- {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']},
+ {'id': 1, 'name': 'target-1',
+ 'sources': ['source-1', 'source-2', 'source-3']},
{'id': 2, 'name': 'target-2', 'sources': []},
]
self.assertEqual(new_serializer.data, expected)
@@ -157,7 +161,8 @@ class SlugForeignKeyTests(TestCase):
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_create(self):
- data = {'id': 3, 'name': 'target-3', 'sources': ['source-1', 'source-3']}
+ data = {'id': 3, 'name': 'target-3',
+ 'sources': ['source-1', 'source-3']}
serializer = ForeignKeyTargetSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
@@ -179,7 +184,8 @@ class SlugForeignKeyTests(TestCase):
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid())
- self.assertEqual(serializer.errors, {'target': ['This field may not be null.']})
+ self.assertEqual(serializer.errors,
+ {'target': ['This field may not be null.']})
class SlugNullableForeignKeyTests(TestCase):
@@ -189,7 +195,8 @@ class SlugNullableForeignKeyTests(TestCase):
for idx in range(1, 4):
if idx == 3:
target = None
- source = NullableForeignKeySource(name='source-%d' % idx, target=target)
+ source = NullableForeignKeySource(name='source-%d' % idx,
+ target=target)
source.save()
def test_foreign_key_retrieve_with_null(self):
diff --git a/tests/test_renderers.py b/tests/test_renderers.py
index a2620e93c..8cc8b42dc 100644
--- a/tests/test_renderers.py
+++ b/tests/test_renderers.py
@@ -3,7 +3,7 @@ from __future__ import unicode_literals
import json
import re
-from collections import MutableMapping, OrderedDict
+from collections import MutableMapping
from django.conf.urls import include, url
from django.core.cache import cache
@@ -14,6 +14,9 @@ from django.utils.safestring import SafeText
from django.utils.translation import ugettext_lazy as _
from rest_framework import permissions, serializers, status
+from rest_framework.fields import (
+ CharField, ChoiceField, HiddenField, MultipleChoiceField, OrderedDict
+)
from rest_framework.renderers import (
BaseRenderer, BrowsableAPIRenderer, HTMLFormRenderer, JSONRenderer
)
@@ -92,7 +95,7 @@ class EmptyGETView(APIView):
class HTMLView(APIView):
- renderer_classes = (BrowsableAPIRenderer, )
+ renderer_classes = (BrowsableAPIRenderer,)
def get(self, request, **kwargs):
return Response('text')
@@ -104,11 +107,14 @@ class HTMLView1(APIView):
def get(self, request, **kwargs):
return Response('text')
+
urlpatterns = [
- url(r'^.*\.(?P.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
+ url(r'^.*\.(?P.+)$',
+ MockView.as_view(renderer_classes=[RendererA, RendererB])),
url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB])),
url(r'^cache$', MockGETView.as_view()),
- url(r'^parseerror$', MockPOSTView.as_view(renderer_classes=[JSONRenderer, BrowsableAPIRenderer])),
+ url(r'^parseerror$', MockPOSTView.as_view(
+ renderer_classes=[JSONRenderer, BrowsableAPIRenderer])),
url(r'^html$', HTMLView.as_view()),
url(r'^html1$', HTMLView1.as_view()),
url(r'^empty$', EmptyGETView.as_view()),
@@ -153,10 +159,13 @@ class RendererEndToEndTests(TestCase):
"""
End-to-end testing of renderers using an RendererMixin on a generic view.
"""
+
def test_default_renderer_serializes_content(self):
- """If the Accept header is not set the default renderer should serialize the response."""
+ """If the Accept header is not set the default renderer should
+ serialize the response."""
resp = self.client.get('/')
- self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@@ -164,34 +173,42 @@ class RendererEndToEndTests(TestCase):
"""No response must be included in HEAD requests."""
resp = self.client.head('/')
self.assertEqual(resp.status_code, DUMMYSTATUS)
- self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, six.b(''))
def test_default_renderer_serializes_content_on_accept_any(self):
- """If the Accept header is set to */* the default renderer should serialize the response."""
+ """If the Accept header is set to */* the default renderer should
+ serialize the response."""
resp = self.client.get('/', HTTP_ACCEPT='*/*')
- self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_specified_renderer_serializes_content_default_case(self):
- """If the Accept header is set the specified renderer should serialize the response.
- (In this case we check that works for the default renderer)"""
+ """If the Accept header is set the specified renderer should serialize
+ the response. (In this case we check that works for the default
+ renderer)"""
resp = self.client.get('/', HTTP_ACCEPT=RendererA.media_type)
- self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_specified_renderer_serializes_content_non_default_case(self):
- """If the Accept header is set the specified renderer should serialize the response.
- (In this case we check that works for a non-default renderer)"""
+ """If the Accept header is set the specified renderer should serialize
+ the response. (In this case we check that works for a non-default
+ renderer)"""
resp = self.client.get('/', HTTP_ACCEPT=RendererB.media_type)
- self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_unsatisfiable_accept_header_on_request_returns_406_status(self):
- """If the Accept header is unsatisfiable we should return a 406 Not Acceptable response."""
+ """If the Accept header is unsatisfiable we should return a
+ 406 Not Acceptable response."""
resp = self.client.get('/', HTTP_ACCEPT='foo/bar')
self.assertEqual(resp.status_code, status.HTTP_406_NOT_ACCEPTABLE)
@@ -203,34 +220,41 @@ class RendererEndToEndTests(TestCase):
RendererB.format
)
resp = self.client.get('/' + param)
- self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_specified_renderer_serializes_content_on_format_kwargs(self):
- """If a 'format' keyword arg is specified, the renderer with the matching
- format attribute should serialize the response."""
+ """If a 'format' keyword arg is specified, the renderer with the
+ matching format attribute should serialize the response."""
resp = self.client.get('/something.formatb')
- self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
- def test_specified_renderer_is_used_on_format_query_with_matching_accept(self):
+ def test_specified_renderer_is_used_on_format_query_with_matching_accept(
+ self):
"""If both a 'format' query and a matching Accept header specified,
- the renderer with the matching format attribute should serialize the response."""
+ the renderer with the matching format attribute should serialize the
+ response."""
param = '?%s=%s' % (
api_settings.URL_FORMAT_OVERRIDE,
RendererB.format
)
resp = self.client.get('/' + param,
HTTP_ACCEPT=RendererB.media_type)
- self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_parse_error_renderers_browsable_api(self):
"""Invalid data should still render the browsable API correctly."""
- resp = self.client.post('/parseerror', data='foobar', content_type='application/json', HTTP_ACCEPT='text/html')
+ resp = self.client.post('/parseerror', data='foobar',
+ content_type='application/json',
+ HTTP_ACCEPT='text/html')
self.assertEqual(resp['Content-Type'], 'text/html; charset=utf-8')
self.assertEqual(resp.status_code, status.HTTP_400_BAD_REQUEST)
@@ -358,18 +382,22 @@ class JSONRendererTests(TestCase):
obj = {'foo': ['bar', 'baz']}
renderer = JSONRenderer()
content = renderer.render(obj, 'application/json; indent=2')
- self.assertEqual(strip_trailing_whitespace(content.decode('utf-8')), _indented_repr)
+ self.assertEqual(strip_trailing_whitespace(content.decode('utf-8')),
+ _indented_repr)
class UnicodeJSONRendererTests(TestCase):
"""
Tests specific for the Unicode JSON Renderer
"""
+
def test_proper_encoding(self):
obj = {'countries': ['United Kingdom', 'France', 'España']}
renderer = JSONRenderer()
content = renderer.render(obj, 'application/json')
- self.assertEqual(content, '{"countries":["United Kingdom","France","España"]}'.encode('utf-8'))
+ self.assertEqual(content,
+ '{"countries":["United Kingdom","France","España"]}'.
+ encode('utf-8'))
def test_u2028_u2029(self):
# The \u2028 and \u2029 characters should be escaped,
@@ -378,20 +406,26 @@ class UnicodeJSONRendererTests(TestCase):
obj = {'should_escape': '\u2028\u2029'}
renderer = JSONRenderer()
content = renderer.render(obj, 'application/json')
- self.assertEqual(content, '{"should_escape":"\\u2028\\u2029"}'.encode('utf-8'))
+ self.assertEqual(content,
+ '{"should_escape":"\\u2028\\u2029"}'.encode('utf-8'))
class AsciiJSONRendererTests(TestCase):
"""
Tests specific for the Unicode JSON Renderer
"""
+
def test_proper_encoding(self):
class AsciiJSONRenderer(JSONRenderer):
ensure_ascii = True
+
obj = {'countries': ['United Kingdom', 'France', 'España']}
renderer = AsciiJSONRenderer()
content = renderer.render(obj, 'application/json')
- self.assertEqual(content, '{"countries":["United Kingdom","France","Espa\\u00f1a"]}'.encode('utf-8'))
+ self.assertEqual(content,
+ '{"countries":["United Kingdom","France",'
+ '"Espa\\u00f1a"]}'.encode(
+ 'utf-8'))
# Tests for caching issue, #346
@@ -400,6 +434,7 @@ class CacheRenderTest(TestCase):
"""
Tests specific to caching responses
"""
+
def test_head_caching(self):
"""
Test caching of HEAD requests
@@ -448,7 +483,7 @@ class TestJSONIndentationStyles:
class TestHiddenFieldHTMLFormRenderer(TestCase):
def test_hidden_field_rendering(self):
class TestSerializer(serializers.Serializer):
- published = serializers.HiddenField(default=True)
+ published = HiddenField(default=True)
serializer = TestSerializer(data={})
serializer.is_valid()
@@ -461,7 +496,7 @@ class TestHiddenFieldHTMLFormRenderer(TestCase):
class TestHTMLFormRenderer(TestCase):
def setUp(self):
class TestSerializer(serializers.Serializer):
- test_field = serializers.CharField()
+ test_field = CharField()
self.renderer = HTMLFormRenderer()
self.serializer = TestSerializer(data={})
@@ -492,8 +527,8 @@ class TestChoiceFieldHTMLFormRenderer(TestCase):
choices = ((1, 'Option1'), (2, 'Option2'), (12, 'Option12'))
class TestSerializer(serializers.Serializer):
- test_field = serializers.ChoiceField(choices=choices,
- initial=2)
+ test_field = ChoiceField(choices=choices,
+ initial=2)
self.TestSerializer = TestSerializer
self.renderer = HTMLFormRenderer()
@@ -536,7 +571,7 @@ class TestMultipleChoiceFieldHTMLFormRenderer(TestCase):
('}', 'OptionBrace'))
class TestSerializer(serializers.Serializer):
- test_field = serializers.MultipleChoiceField(choices=choices)
+ test_field = MultipleChoiceField(choices=choices)
serializer = TestSerializer(data={'test_field': ['12']})
serializer.is_valid()
@@ -555,7 +590,7 @@ class TestMultipleChoiceFieldHTMLFormRenderer(TestCase):
choices = ((1, 'Option1'), (2, 'Option2'), (12, 'Option12'))
class TestSerializer(serializers.Serializer):
- test_field = serializers.MultipleChoiceField(choices=choices)
+ test_field = MultipleChoiceField(choices=choices)
serializer = TestSerializer(data={'test_field': ['12']})
serializer.is_valid()
diff --git a/tests/test_response.py b/tests/test_response.py
index 33c51e773..52fd47d33 100644
--- a/tests/test_response.py
+++ b/tests/test_response.py
@@ -32,6 +32,7 @@ class MockJsonRenderer(BaseRenderer):
class MockTextMediaRenderer(BaseRenderer):
media_type = 'text/html'
+
DUMMYSTATUS = status.HTTP_200_OK
DUMMYCONTENT = 'dummycontent'
@@ -77,7 +78,8 @@ class MockViewSettingContentType(APIView):
renderer_classes = (RendererA, RendererB, RendererC)
def get(self, request, **kwargs):
- return Response(DUMMYCONTENT, status=DUMMYSTATUS, content_type='setbyview')
+ return Response(DUMMYCONTENT, status=DUMMYSTATUS,
+ content_type='setbyview')
class JSONView(APIView):
@@ -89,7 +91,7 @@ class JSONView(APIView):
class HTMLView(APIView):
- renderer_classes = (BrowsableAPIRenderer, )
+ renderer_classes = (BrowsableAPIRenderer,)
def get(self, request, **kwargs):
return Response('text')
@@ -117,17 +119,20 @@ class HTMLNewModelView(generics.ListCreateAPIView):
new_model_viewset_router = routers.DefaultRouter()
new_model_viewset_router.register(r'', HTMLNewModelViewSet)
-
urlpatterns = [
- url(r'^setbyview$', MockViewSettingContentType.as_view(renderer_classes=[RendererA, RendererB, RendererC])),
- url(r'^.*\.(?P.+)$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])),
- url(r'^$', MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])),
+ url(r'^setbyview$', MockViewSettingContentType.as_view(
+ renderer_classes=[RendererA, RendererB, RendererC])),
+ url(r'^.*\.(?P.+)$',
+ MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])),
+ url(r'^$',
+ MockView.as_view(renderer_classes=[RendererA, RendererB, RendererC])),
url(r'^html$', HTMLView.as_view()),
url(r'^json$', JSONView.as_view()),
url(r'^html1$', HTMLView1.as_view()),
url(r'^html_new_model$', HTMLNewModelView.as_view()),
url(r'^html_new_model_viewset', include(new_model_viewset_router.urls)),
- url(r'^restframework', include('rest_framework.urls', namespace='rest_framework'))
+ url(r'^restframework',
+ include('rest_framework.urls', namespace='rest_framework'))
]
@@ -137,10 +142,13 @@ class RendererIntegrationTests(TestCase):
"""
End-to-end testing of renderers using an ResponseMixin on a generic view.
"""
+
def test_default_renderer_serializes_content(self):
- """If the Accept header is not set the default renderer should serialize the response."""
+ """If the Accept header is not set the default renderer should
+ serialize the response."""
resp = self.client.get('/')
- self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@@ -148,29 +156,36 @@ class RendererIntegrationTests(TestCase):
"""No response must be included in HEAD requests."""
resp = self.client.head('/')
self.assertEqual(resp.status_code, DUMMYSTATUS)
- self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, six.b(''))
def test_default_renderer_serializes_content_on_accept_any(self):
- """If the Accept header is set to */* the default renderer should serialize the response."""
+ """If the Accept header is set to */* the default renderer should
+ serialize the response."""
resp = self.client.get('/', HTTP_ACCEPT='*/*')
- self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_specified_renderer_serializes_content_default_case(self):
- """If the Accept header is set the specified renderer should serialize the response.
+ """If the Accept header is set the specified renderer should serialize
+ the response.
(In this case we check that works for the default renderer)"""
resp = self.client.get('/', HTTP_ACCEPT=RendererA.media_type)
- self.assertEqual(resp['Content-Type'], RendererA.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererA.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_A_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_specified_renderer_serializes_content_non_default_case(self):
- """If the Accept header is set the specified renderer should serialize the response.
+ """If the Accept header is set the specified renderer should serialize
+ the response.
(In this case we check that works for a non-default renderer)"""
resp = self.client.get('/', HTTP_ACCEPT=RendererB.media_type)
- self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@@ -178,24 +193,29 @@ class RendererIntegrationTests(TestCase):
"""If a 'format' query is specified, the renderer with the matching
format attribute should serialize the response."""
resp = self.client.get('/?format=%s' % RendererB.format)
- self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
def test_specified_renderer_serializes_content_on_format_kwargs(self):
- """If a 'format' keyword arg is specified, the renderer with the matching
- format attribute should serialize the response."""
+ """If a 'format' keyword arg is specified, the renderer with the
+ matching format attribute should serialize the response."""
resp = self.client.get('/something.formatb')
- self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
- def test_specified_renderer_is_used_on_format_query_with_matching_accept(self):
+ def test_specified_renderer_is_used_on_format_query_with_matching_accept(
+ self):
"""If both a 'format' query and a matching Accept header specified,
- the renderer with the matching format attribute should serialize the response."""
+ the renderer with the matching format attribute should serialize the
+ response."""
resp = self.client.get('/?format=%s' % RendererB.format,
HTTP_ACCEPT=RendererB.media_type)
- self.assertEqual(resp['Content-Type'], RendererB.media_type + '; charset=utf-8')
+ self.assertEqual(resp['Content-Type'],
+ RendererB.media_type + '; charset=utf-8')
self.assertEqual(resp.content, RENDERER_B_SERIALIZER(DUMMYCONTENT))
self.assertEqual(resp.status_code, DUMMYSTATUS)
@@ -203,12 +223,14 @@ class RendererIntegrationTests(TestCase):
@override_settings(ROOT_URLCONF='tests.test_response')
class UnsupportedMediaTypeTests(TestCase):
def test_should_allow_posting_json(self):
- response = self.client.post('/json', data='{"test": 123}', content_type='application/json')
+ response = self.client.post('/json', data='{"test": 123}',
+ content_type='application/json')
self.assertEqual(response.status_code, 200)
def test_should_not_allow_posting_xml(self):
- response = self.client.post('/json', data='123', content_type='application/xml')
+ response = self.client.post('/json', data='123',
+ content_type='application/xml')
self.assertEqual(response.status_code, 415)
@@ -223,6 +245,7 @@ class Issue122Tests(TestCase):
"""
Tests that covers #122.
"""
+
def test_only_html_renderer(self):
"""
Test if no infinite recursion occurs.
@@ -241,6 +264,7 @@ class Issue467Tests(TestCase):
"""
Tests for #467
"""
+
def test_form_has_label_and_help_text(self):
resp = self.client.get('/html_new_model')
self.assertEqual(resp['Content-Type'], 'text/html; charset=utf-8')
@@ -253,6 +277,7 @@ class Issue807Tests(TestCase):
"""
Covers #807
"""
+
def test_does_not_append_charset_by_default(self):
"""
Renderers don't include a charset unless set explicitly.
@@ -269,7 +294,8 @@ class Issue807Tests(TestCase):
"""
headers = {"HTTP_ACCEPT": RendererC.media_type}
resp = self.client.get('/', **headers)
- expected = "{0}; charset={1}".format(RendererC.media_type, RendererC.charset)
+ expected = "{0}; charset={1}".format(RendererC.media_type,
+ RendererC.charset)
self.assertEqual(expected, resp['Content-Type'])
def test_content_type_set_explicitly_on_response(self):
diff --git a/tests/test_serializer.py b/tests/test_serializer.py
index 32be39faa..1e8021780 100644
--- a/tests/test_serializer.py
+++ b/tests/test_serializer.py
@@ -8,6 +8,9 @@ import pytest
from rest_framework import serializers
from rest_framework.compat import unicode_repr
+from rest_framework.fields import (
+ CharField, IntegerField, RegexField, ValidationError
+)
from .utils import MockObject
@@ -18,8 +21,9 @@ from .utils import MockObject
class TestSerializer:
def setup(self):
class ExampleSerializer(serializers.Serializer):
- char = serializers.CharField()
- integer = serializers.IntegerField()
+ char = CharField()
+ integer = IntegerField()
+
self.Serializer = ExampleSerializer
def test_valid_serializer(self):
@@ -47,6 +51,7 @@ class TestSerializer:
def test_missing_attribute_during_serialization(self):
class MissingAttributes:
pass
+
instance = MissingAttributes()
serializer = self.Serializer(instance)
with pytest.raises(AttributeError):
@@ -55,6 +60,7 @@ class TestSerializer:
def test_data_access_before_save_raises_error(self):
def create(validated_data):
return validated_data
+
serializer = self.Serializer(data={'char': 'abc', 'integer': 123})
serializer.create = create
assert serializer.is_valid()
@@ -72,11 +78,11 @@ class TestSerializer:
class TestValidateMethod:
def test_non_field_error_validate_method(self):
class ExampleSerializer(serializers.Serializer):
- char = serializers.CharField()
- integer = serializers.IntegerField()
+ char = CharField()
+ integer = IntegerField()
def validate(self, attrs):
- raise serializers.ValidationError('Non field error')
+ raise ValidationError('Non field error')
serializer = ExampleSerializer(data={'char': 'abc', 'integer': 123})
assert not serializer.is_valid()
@@ -84,11 +90,11 @@ class TestValidateMethod:
def test_field_error_validate_method(self):
class ExampleSerializer(serializers.Serializer):
- char = serializers.CharField()
- integer = serializers.IntegerField()
+ char = CharField()
+ integer = IntegerField()
def validate(self, attrs):
- raise serializers.ValidationError({'char': 'Field error'})
+ raise ValidationError({'char': 'Field error'})
serializer = ExampleSerializer(data={'char': 'abc', 'integer': 123})
assert not serializer.is_valid()
@@ -168,12 +174,12 @@ class TestStarredSource:
def setup(self):
class NestedSerializer1(serializers.Serializer):
- a = serializers.IntegerField()
- b = serializers.IntegerField()
+ a = IntegerField()
+ b = IntegerField()
class NestedSerializer2(serializers.Serializer):
- c = serializers.IntegerField()
- d = serializers.IntegerField()
+ c = IntegerField()
+ d = IntegerField()
class TestSerializer(serializers.Serializer):
nested1 = NestedSerializer1(source='*')
@@ -206,7 +212,7 @@ class TestStarredSource:
class TestIncorrectlyConfigured:
def test_incorrect_field_name(self):
class ExampleSerializer(serializers.Serializer):
- incorrect_name = serializers.IntegerField()
+ incorrect_name = IntegerField()
class ExampleObject:
def __init__(self):
@@ -227,7 +233,7 @@ class TestIncorrectlyConfigured:
class TestUnicodeRepr:
def test_unicode_repr(self):
class ExampleSerializer(serializers.Serializer):
- example = serializers.CharField()
+ example = CharField()
class ExampleObject:
def __init__(self):
@@ -246,9 +252,10 @@ class TestNotRequiredOutput:
"""
'required=False' should allow a dictionary key to be missing in output.
"""
+
class ExampleSerializer(serializers.Serializer):
- omitted = serializers.CharField(required=False)
- included = serializers.CharField()
+ omitted = CharField(required=False)
+ included = CharField()
serializer = ExampleSerializer(data={'included': 'abc'})
serializer.is_valid()
@@ -258,9 +265,10 @@ class TestNotRequiredOutput:
"""
'required=False' should allow an object attribute to be missing in output.
"""
+
class ExampleSerializer(serializers.Serializer):
- omitted = serializers.CharField(required=False)
- included = serializers.CharField()
+ omitted = CharField(required=False)
+ included = CharField()
def create(self, validated_data):
return MockObject(**validated_data)
@@ -277,9 +285,10 @@ class TestNotRequiredOutput:
We need to handle this as the field will have an implicit
'required=False', but it should still have a value.
"""
+
class ExampleSerializer(serializers.Serializer):
- omitted = serializers.CharField(default='abc')
- included = serializers.CharField()
+ omitted = CharField(default='abc')
+ included = CharField()
serializer = ExampleSerializer({'included': 'abc'})
with pytest.raises(KeyError):
@@ -292,9 +301,10 @@ class TestNotRequiredOutput:
We need to handle this as the field will have an implicit
'required=False', but it should still have a value.
"""
+
class ExampleSerializer(serializers.Serializer):
- omitted = serializers.CharField(default='abc')
- included = serializers.CharField()
+ omitted = CharField(default='abc')
+ included = CharField()
instance = MockObject(included='abc')
serializer = ExampleSerializer(instance)
@@ -308,9 +318,10 @@ class TestCacheSerializerData:
Caching serializer data with pickle will drop the serializer info,
but does preserve the data itself.
"""
+
class ExampleSerializer(serializers.Serializer):
- field1 = serializers.CharField()
- field2 = serializers.CharField()
+ field1 = CharField()
+ field2 = CharField()
serializer = ExampleSerializer({'field1': 'a', 'field2': 'b'})
pickled = pickle.dumps(serializer.data)
@@ -321,8 +332,9 @@ class TestCacheSerializerData:
class TestDefaultInclusions:
def setup(self):
class ExampleSerializer(serializers.Serializer):
- char = serializers.CharField(read_only=True, default='abc')
- integer = serializers.IntegerField()
+ char = CharField(read_only=True, default='abc')
+ integer = IntegerField()
+
self.Serializer = ExampleSerializer
def test_default_should_included_on_create(self):
@@ -340,7 +352,8 @@ class TestDefaultInclusions:
def test_default_should_not_be_included_on_partial_update(self):
instance = MockObject(char='def', integer=123)
- serializer = self.Serializer(instance, data={'integer': 456}, partial=True)
+ serializer = self.Serializer(instance, data={'integer': 456},
+ partial=True)
assert serializer.is_valid()
assert serializer.validated_data == {'integer': 456}
assert serializer.errors == {}
@@ -349,7 +362,8 @@ class TestDefaultInclusions:
class TestSerializerValidationWithCompiledRegexField:
def setup(self):
class ExampleSerializer(serializers.Serializer):
- name = serializers.RegexField(re.compile(r'\d'), required=True)
+ name = RegexField(re.compile(r'\d'), required=True)
+
self.Serializer = ExampleSerializer
def test_validation_success(self):
diff --git a/tests/test_serializer_lists.py b/tests/test_serializer_lists.py
index 607ddba04..a4f89718d 100644
--- a/tests/test_serializer_lists.py
+++ b/tests/test_serializer_lists.py
@@ -1,12 +1,17 @@
from django.utils.datastructures import MultiValueDict
from rest_framework import serializers
+from rest_framework.fields import (
+ BooleanField, IntegerField, ListField, MultipleChoiceField,
+ ValidationError
+)
class BasicObject:
"""
A mock object for testing serializer save behavior.
"""
+
def __init__(self, **kwargs):
self._data = kwargs
for key, value in kwargs.items():
@@ -29,7 +34,8 @@ class TestListSerializer:
def setup(self):
class IntegerListSerializer(serializers.ListSerializer):
- child = serializers.IntegerField()
+ child = IntegerField()
+
self.Serializer = IntegerListSerializer
def test_validate(self):
@@ -60,8 +66,8 @@ class TestListSerializerContainingNestedSerializer:
def setup(self):
class TestSerializer(serializers.Serializer):
- integer = serializers.IntegerField()
- boolean = serializers.BooleanField()
+ integer = IntegerField()
+ boolean = BooleanField()
def create(self, validated_data):
return BasicObject(**validated_data)
@@ -146,8 +152,8 @@ class TestNestedListSerializer:
def setup(self):
class TestSerializer(serializers.Serializer):
- integers = serializers.ListSerializer(child=serializers.IntegerField())
- booleans = serializers.ListSerializer(child=serializers.BooleanField())
+ integers = serializers.ListSerializer(child=IntegerField())
+ booleans = serializers.ListSerializer(child=BooleanField())
def create(self, validated_data):
return BasicObject(**validated_data)
@@ -227,12 +233,12 @@ class TestNestedListOfListsSerializer:
class TestSerializer(serializers.Serializer):
integers = serializers.ListSerializer(
child=serializers.ListSerializer(
- child=serializers.IntegerField()
+ child=IntegerField()
)
)
booleans = serializers.ListSerializer(
child=serializers.ListSerializer(
- child=serializers.BooleanField()
+ child=BooleanField()
)
)
@@ -277,10 +283,11 @@ class TestNestedListOfListsSerializer:
class TestListSerializerClass:
"""Tests for a custom list_serializer_class."""
+
def test_list_serializer_class_validate(self):
class CustomListSerializer(serializers.ListSerializer):
def validate(self, attrs):
- raise serializers.ValidationError('Non field error')
+ raise ValidationError('Non field error')
class TestSerializer(serializers.Serializer):
class Meta:
@@ -299,9 +306,11 @@ class TestSerializerPartialUsage:
Regression test for Github issue #2761.
"""
+
def test_partial_listfield(self):
class ListSerializer(serializers.Serializer):
- listdata = serializers.ListField()
+ listdata = ListField()
+
serializer = ListSerializer(data=MultiValueDict(), partial=True)
result = serializer.to_internal_value(data={})
assert "listdata" not in result
@@ -311,8 +320,10 @@ class TestSerializerPartialUsage:
def test_partial_multiplechoice(self):
class MultipleChoiceSerializer(serializers.Serializer):
- multiplechoice = serializers.MultipleChoiceField(choices=[1, 2, 3])
- serializer = MultipleChoiceSerializer(data=MultiValueDict(), partial=True)
+ multiplechoice = MultipleChoiceField(choices=[1, 2, 3])
+
+ serializer = MultipleChoiceSerializer(data=MultiValueDict(),
+ partial=True)
result = serializer.to_internal_value(data={})
assert "multiplechoice" not in result
assert serializer.is_valid()
diff --git a/tests/test_serializer_nested.py b/tests/test_serializer_nested.py
index efb671918..911cbe4ff 100644
--- a/tests/test_serializer_nested.py
+++ b/tests/test_serializer_nested.py
@@ -1,13 +1,14 @@
from django.http import QueryDict
from rest_framework import serializers
+from rest_framework.fields import IntegerField, MultipleChoiceField
class TestNestedSerializer:
def setup(self):
class NestedSerializer(serializers.Serializer):
- one = serializers.IntegerField(max_value=10)
- two = serializers.IntegerField(max_value=10)
+ one = IntegerField(max_value=10)
+ two = IntegerField(max_value=10)
class TestSerializer(serializers.Serializer):
nested = NestedSerializer()
@@ -51,7 +52,7 @@ class TestNestedSerializer:
class TestNotRequiredNestedSerializer:
def setup(self):
class NestedSerializer(serializers.Serializer):
- one = serializers.IntegerField(max_value=10)
+ one = IntegerField(max_value=10)
class TestSerializer(serializers.Serializer):
nested = NestedSerializer(required=False)
@@ -80,7 +81,7 @@ class TestNotRequiredNestedSerializer:
class TestNestedSerializerWithMany:
def setup(self):
class NestedSerializer(serializers.Serializer):
- example = serializers.IntegerField(max_value=10)
+ example = IntegerField(max_value=10)
class TestSerializer(serializers.Serializer):
allow_null = NestedSerializer(many=True, allow_null=True)
@@ -119,7 +120,8 @@ class TestNestedSerializerWithMany:
assert not serializer.is_valid()
- expected_errors = {'not_allow_null': [serializer.error_messages['null']]}
+ expected_errors = {
+ 'not_allow_null': [serializer.error_messages['null']]}
assert serializer.errors == expected_errors
def test_run_the_field_validation_even_if_the_field_is_null(self):
@@ -171,14 +173,15 @@ class TestNestedSerializerWithMany:
assert not serializer.is_valid()
- expected_errors = {'not_allow_empty': {'non_field_errors': [serializers.ListSerializer.default_error_messages['empty']]}}
+ expected_errors = {'not_allow_empty': {'non_field_errors': [
+ serializers.ListSerializer.default_error_messages['empty']]}}
assert serializer.errors == expected_errors
class TestNestedSerializerWithList:
def setup(self):
class NestedSerializer(serializers.Serializer):
- example = serializers.MultipleChoiceField(choices=[1, 2, 3])
+ example = MultipleChoiceField(choices=[1, 2, 3])
class TestSerializer(serializers.Serializer):
nested = NestedSerializer()
diff --git a/tests/test_utils.py b/tests/test_utils.py
index 23b0013b2..fa9669adc 100644
--- a/tests/test_utils.py
+++ b/tests/test_utils.py
@@ -43,7 +43,8 @@ urlpatterns = [
url(r'^resource/customname$', CustomNameResourceInstance.as_view()),
url(r'^resource/(?P[0-9]+)$', ResourceInstance.as_view()),
url(r'^resource/(?P[0-9]+)/$', NestedResourceRoot.as_view()),
- url(r'^resource/(?P[0-9]+)/(?P[A-Za-z]+)$', NestedResourceInstance.as_view()),
+ url(r'^resource/(?P[0-9]+)/(?P[A-Za-z]+)$',
+ NestedResourceInstance.as_view()),
]
@@ -52,6 +53,7 @@ class BreadcrumbTests(TestCase):
"""
Tests the breadcrumb functionality used by the HTML renderer.
"""
+
def test_root_breadcrumbs(self):
url = '/'
self.assertEqual(
@@ -130,6 +132,7 @@ class ResolveModelTests(TestCase):
provided argument is a Django model class itself, or a properly
formatted string representation of one.
"""
+
def test_resolve_django_model(self):
resolved_model = _resolve_model(BasicModel)
self.assertEqual(resolved_model, BasicModel)
diff --git a/tests/utils.py b/tests/utils.py
index 52582f093..811c6d6c6 100644
--- a/tests/utils.py
+++ b/tests/utils.py
@@ -1,4 +1,5 @@
from django.core.exceptions import ObjectDoesNotExist
+
from rest_framework.compat import NoReverseMatch