mirror of
https://github.com/encode/django-rest-framework.git
synced 2025-01-23 15:54:16 +03:00
Merge branch 'p3k' of https://github.com/linovia/django-rest-framework into working
Conflicts: rest_framework/authentication.py rest_framework/relations.py rest_framework/serializers.py rest_framework/settings.py rest_framework/tests/authentication.py rest_framework/tests/genericrelations.py rest_framework/tests/generics.py rest_framework/tests/relations_hyperlink.py rest_framework/tests/relations_nested.py rest_framework/tests/relations_pk.py rest_framework/tests/serializer.py
This commit is contained in:
commit
d9c7b1c585
17
.travis.yml
17
.travis.yml
|
@ -3,16 +3,27 @@ language: python
|
||||||
python:
|
python:
|
||||||
- "2.6"
|
- "2.6"
|
||||||
- "2.7"
|
- "2.7"
|
||||||
|
- "3.2"
|
||||||
|
|
||||||
env:
|
env:
|
||||||
- DJANGO=https://github.com/django/django/zipball/master
|
- DJANGO=https://github.com/django/django/zipball/master
|
||||||
- DJANGO=django==1.4.3 --use-mirrors
|
- DJANGO=https://www.djangoproject.com/download/1.5c1/tarball/
|
||||||
- DJANGO=django==1.3.5 --use-mirrors
|
- DJANGO="django==1.4.3 --use-mirrors"
|
||||||
|
- DJANGO="django==1.3.5 --use-mirrors"
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install $DJANGO
|
- pip install $DJANGO
|
||||||
- pip install django-filter==0.5.4 --use-mirrors
|
- "if [[ $TRAVIS_PYTHON_VERSION != '3.2' ]]; then pip install django-filter==0.5.4 --use-mirrors; fi"
|
||||||
|
- "if [[ $TRAVIS_PYTHON_VERSION == '3.2' ]]; then pip install https://github.com/alex/django-filter/tarball/master; fi"
|
||||||
|
- "if [[ $DJANGO == 'django==1.3.5 --use-mirrors' ]]; then pip install six --use-mirrors; fi"
|
||||||
- export PYTHONPATH=.
|
- export PYTHONPATH=.
|
||||||
|
|
||||||
script:
|
script:
|
||||||
- python rest_framework/runtests/runtests.py
|
- python rest_framework/runtests/runtests.py
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
exclude:
|
||||||
|
- python: "3.2"
|
||||||
|
env: DJANGO="django==1.4.3 --use-mirrors"
|
||||||
|
- python: "3.2"
|
||||||
|
env: DJANGO="django==1.3.5 --use-mirrors"
|
||||||
|
|
|
@ -3,10 +3,12 @@ Provides a set of pluggable authentication policies.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from django.contrib.auth import authenticate
|
from django.contrib.auth import authenticate
|
||||||
from django.utils.encoding import smart_unicode, DjangoUnicodeDecodeError
|
from django.utils.encoding import DjangoUnicodeDecodeError
|
||||||
from rest_framework import exceptions
|
from rest_framework import exceptions
|
||||||
from rest_framework.compat import CsrfViewMiddleware
|
from rest_framework.compat import CsrfViewMiddleware
|
||||||
|
from rest_framework.compat import smart_text
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
|
from rest_framework.settings import api_settings
|
||||||
import base64
|
import base64
|
||||||
|
|
||||||
|
|
||||||
|
@ -49,14 +51,15 @@ class BasicAuthentication(BaseAuthentication):
|
||||||
if len(auth) != 2:
|
if len(auth) != 2:
|
||||||
raise exceptions.AuthenticationFailed('Invalid basic header')
|
raise exceptions.AuthenticationFailed('Invalid basic header')
|
||||||
|
|
||||||
|
encoding = api_settings.HTTP_HEADER_ENCODING
|
||||||
try:
|
try:
|
||||||
auth_parts = base64.b64decode(auth[1]).partition(':')
|
auth_parts = base64.b64decode(auth[1].encode(encoding)).partition(':')
|
||||||
except TypeError:
|
except TypeError:
|
||||||
raise exceptions.AuthenticationFailed('Invalid basic header')
|
raise exceptions.AuthenticationFailed('Invalid basic header')
|
||||||
|
|
||||||
try:
|
try:
|
||||||
userid = smart_unicode(auth_parts[0])
|
userid = smart_text(auth_parts[0])
|
||||||
password = smart_unicode(auth_parts[2])
|
password = smart_text(auth_parts[2])
|
||||||
except DjangoUnicodeDecodeError:
|
except DjangoUnicodeDecodeError:
|
||||||
raise exceptions.AuthenticationFailed('Invalid basic header')
|
raise exceptions.AuthenticationFailed('Invalid basic header')
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@ class Token(models.Model):
|
||||||
return super(Token, self).save(*args, **kwargs)
|
return super(Token, self).save(*args, **kwargs)
|
||||||
|
|
||||||
def generate_key(self):
|
def generate_key(self):
|
||||||
unique = str(uuid.uuid4())
|
unique = uuid.uuid4()
|
||||||
return hmac.new(unique, digestmod=sha1).hexdigest()
|
return hmac.new(unique.bytes, digestmod=sha1).hexdigest()
|
||||||
|
|
||||||
def __unicode__(self):
|
def __unicode__(self):
|
||||||
return self.key
|
return self.key
|
||||||
|
|
|
@ -3,14 +3,35 @@ The `compat` module provides support for backwards compatibility with older
|
||||||
versions of django/python, and compatibility wrappers around optional packages.
|
versions of django/python, and compatibility wrappers around optional packages.
|
||||||
"""
|
"""
|
||||||
# flake8: noqa
|
# flake8: noqa
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import django
|
import django
|
||||||
|
|
||||||
|
# Try to import six from Django, fallback to six itself (1.3.x)
|
||||||
|
try:
|
||||||
|
from django.utils import six
|
||||||
|
except:
|
||||||
|
import six
|
||||||
|
|
||||||
# location of patterns, url, include changes in 1.4 onwards
|
# location of patterns, url, include changes in 1.4 onwards
|
||||||
try:
|
try:
|
||||||
from django.conf.urls import patterns, url, include
|
from django.conf.urls import patterns, url, include
|
||||||
except:
|
except:
|
||||||
from django.conf.urls.defaults import patterns, url, include
|
from django.conf.urls.defaults import patterns, url, include
|
||||||
|
|
||||||
|
# Handle django.utils.encoding rename:
|
||||||
|
# smart_unicode -> smart_text
|
||||||
|
# force_unicode -> force_text
|
||||||
|
try:
|
||||||
|
from django.utils.encoding import smart_text
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.encoding import smart_unicode as smart_text
|
||||||
|
try:
|
||||||
|
from django.utils.encoding import force_text
|
||||||
|
except ImportError:
|
||||||
|
from django.utils.encoding import force_unicode as force_text
|
||||||
|
|
||||||
|
|
||||||
# django-filter is optional
|
# django-filter is optional
|
||||||
try:
|
try:
|
||||||
import django_filters
|
import django_filters
|
||||||
|
@ -20,9 +41,18 @@ except:
|
||||||
|
|
||||||
# cStringIO only if it's available, otherwise StringIO
|
# cStringIO only if it's available, otherwise StringIO
|
||||||
try:
|
try:
|
||||||
import cStringIO as StringIO
|
import cStringIO.StringIO as StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import StringIO
|
StringIO = six.StringIO
|
||||||
|
|
||||||
|
BytesIO = six.BytesIO
|
||||||
|
|
||||||
|
|
||||||
|
# urlparse compat import (Required because it changed in python 3.x)
|
||||||
|
try:
|
||||||
|
from urllib import parse as urlparse
|
||||||
|
except ImportError:
|
||||||
|
import urlparse
|
||||||
|
|
||||||
|
|
||||||
# Try to import PIL in either of the two ways it can end up installed.
|
# Try to import PIL in either of the two ways it can end up installed.
|
||||||
|
@ -54,7 +84,7 @@ else:
|
||||||
try:
|
try:
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise ImportError(u"User model is not to be found.")
|
raise ImportError("User model is not to be found.")
|
||||||
|
|
||||||
|
|
||||||
# First implementation of Django class-based views did not include head method
|
# First implementation of Django class-based views did not include head method
|
||||||
|
@ -75,11 +105,11 @@ else:
|
||||||
# sanitize keyword arguments
|
# sanitize keyword arguments
|
||||||
for key in initkwargs:
|
for key in initkwargs:
|
||||||
if key in cls.http_method_names:
|
if key in cls.http_method_names:
|
||||||
raise TypeError(u"You tried to pass in the %s method name as a "
|
raise TypeError("You tried to pass in the %s method name as a "
|
||||||
u"keyword argument to %s(). Don't do that."
|
"keyword argument to %s(). Don't do that."
|
||||||
% (key, cls.__name__))
|
% (key, cls.__name__))
|
||||||
if not hasattr(cls, key):
|
if not hasattr(cls, key):
|
||||||
raise TypeError(u"%s() received an invalid keyword %r" % (
|
raise TypeError("%s() received an invalid keyword %r" % (
|
||||||
cls.__name__, key))
|
cls.__name__, key))
|
||||||
|
|
||||||
def view(request, *args, **kwargs):
|
def view(request, *args, **kwargs):
|
||||||
|
@ -110,7 +140,6 @@ else:
|
||||||
import re
|
import re
|
||||||
import random
|
import random
|
||||||
import logging
|
import logging
|
||||||
import urlparse
|
|
||||||
|
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.core.urlresolvers import get_callable
|
from django.core.urlresolvers import get_callable
|
||||||
|
@ -152,7 +181,8 @@ else:
|
||||||
randrange = random.SystemRandom().randrange
|
randrange = random.SystemRandom().randrange
|
||||||
else:
|
else:
|
||||||
randrange = random.randrange
|
randrange = random.randrange
|
||||||
_MAX_CSRF_KEY = 18446744073709551616L # 2 << 63
|
|
||||||
|
_MAX_CSRF_KEY = 18446744073709551616 # 2 << 63
|
||||||
|
|
||||||
REASON_NO_REFERER = "Referer checking failed - no Referer."
|
REASON_NO_REFERER = "Referer checking failed - no Referer."
|
||||||
REASON_BAD_REFERER = "Referer checking failed - %s does not match %s."
|
REASON_BAD_REFERER = "Referer checking failed - %s does not match %s."
|
||||||
|
|
|
@ -1,20 +1,23 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import datetime
|
import datetime
|
||||||
import inspect
|
import inspect
|
||||||
import re
|
import re
|
||||||
import warnings
|
import warnings
|
||||||
|
|
||||||
from io import BytesIO
|
|
||||||
|
|
||||||
from django.core import validators
|
from django.core import validators
|
||||||
from django.core.exceptions import ValidationError
|
from django.core.exceptions import ValidationError
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
from django.utils.encoding import is_protected_type, smart_unicode
|
from django.utils.encoding import is_protected_type
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework.compat import parse_date, parse_datetime
|
from rest_framework.compat import parse_date, parse_datetime
|
||||||
from rest_framework.compat import timezone
|
from rest_framework.compat import timezone
|
||||||
|
from rest_framework.compat import BytesIO
|
||||||
|
from rest_framework.compat import six
|
||||||
|
from rest_framework.compat import smart_text
|
||||||
|
|
||||||
|
|
||||||
def is_simple_callable(obj):
|
def is_simple_callable(obj):
|
||||||
|
@ -93,11 +96,11 @@ class Field(object):
|
||||||
|
|
||||||
if is_protected_type(value):
|
if is_protected_type(value):
|
||||||
return value
|
return value
|
||||||
elif hasattr(value, '__iter__') and not isinstance(value, (dict, basestring)):
|
elif hasattr(value, '__iter__') and not isinstance(value, (dict, six.string_types)):
|
||||||
return [self.to_native(item) for item in value]
|
return [self.to_native(item) for item in value]
|
||||||
elif isinstance(value, dict):
|
elif isinstance(value, dict):
|
||||||
return dict(map(self.to_native, (k, v)) for k, v in value.items())
|
return dict(map(self.to_native, (k, v)) for k, v in value.items())
|
||||||
return smart_unicode(value)
|
return smart_text(value)
|
||||||
|
|
||||||
def attributes(self):
|
def attributes(self):
|
||||||
"""
|
"""
|
||||||
|
@ -258,7 +261,7 @@ class BooleanField(WritableField):
|
||||||
form_field_class = forms.BooleanField
|
form_field_class = forms.BooleanField
|
||||||
widget = widgets.CheckboxInput
|
widget = widgets.CheckboxInput
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _(u"'%s' value must be either True or False."),
|
'invalid': _("'%s' value must be either True or False."),
|
||||||
}
|
}
|
||||||
empty = False
|
empty = False
|
||||||
|
|
||||||
|
@ -298,9 +301,9 @@ class CharField(WritableField):
|
||||||
super(CharField, self).validate(value)
|
super(CharField, self).validate(value)
|
||||||
|
|
||||||
def from_native(self, value):
|
def from_native(self, value):
|
||||||
if isinstance(value, basestring) or value is None:
|
if isinstance(value, six.string_types) or value is None:
|
||||||
return value
|
return value
|
||||||
return smart_unicode(value)
|
return smart_text(value)
|
||||||
|
|
||||||
|
|
||||||
class URLField(CharField):
|
class URLField(CharField):
|
||||||
|
@ -359,10 +362,10 @@ class ChoiceField(WritableField):
|
||||||
if isinstance(v, (list, tuple)):
|
if isinstance(v, (list, tuple)):
|
||||||
# This is an optgroup, so look inside the group for options
|
# This is an optgroup, so look inside the group for options
|
||||||
for k2, v2 in v:
|
for k2, v2 in v:
|
||||||
if value == smart_unicode(k2):
|
if value == smart_text(k2):
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
if value == smart_unicode(k) or value == k:
|
if value == smart_text(k) or value == k:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -402,7 +405,7 @@ class RegexField(CharField):
|
||||||
return self._regex
|
return self._regex
|
||||||
|
|
||||||
def _set_regex(self, regex):
|
def _set_regex(self, regex):
|
||||||
if isinstance(regex, basestring):
|
if isinstance(regex, six.string_types):
|
||||||
regex = re.compile(regex)
|
regex = re.compile(regex)
|
||||||
self._regex = regex
|
self._regex = regex
|
||||||
if hasattr(self, '_regex_validator') and self._regex_validator in self.validators:
|
if hasattr(self, '_regex_validator') and self._regex_validator in self.validators:
|
||||||
|
@ -425,10 +428,10 @@ class DateField(WritableField):
|
||||||
form_field_class = forms.DateField
|
form_field_class = forms.DateField
|
||||||
|
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _(u"'%s' value has an invalid date format. It must be "
|
'invalid': _("'%s' value has an invalid date format. It must be "
|
||||||
u"in YYYY-MM-DD format."),
|
"in YYYY-MM-DD format."),
|
||||||
'invalid_date': _(u"'%s' value has the correct format (YYYY-MM-DD) "
|
'invalid_date': _("'%s' value has the correct format (YYYY-MM-DD) "
|
||||||
u"but it is an invalid date."),
|
"but it is an invalid date."),
|
||||||
}
|
}
|
||||||
empty = None
|
empty = None
|
||||||
|
|
||||||
|
@ -464,13 +467,13 @@ class DateTimeField(WritableField):
|
||||||
form_field_class = forms.DateTimeField
|
form_field_class = forms.DateTimeField
|
||||||
|
|
||||||
default_error_messages = {
|
default_error_messages = {
|
||||||
'invalid': _(u"'%s' value has an invalid format. It must be in "
|
'invalid': _("'%s' value has an invalid format. It must be in "
|
||||||
u"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format."),
|
"YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ] format."),
|
||||||
'invalid_date': _(u"'%s' value has the correct format "
|
'invalid_date': _("'%s' value has the correct format "
|
||||||
u"(YYYY-MM-DD) but it is an invalid date."),
|
"(YYYY-MM-DD) but it is an invalid date."),
|
||||||
'invalid_datetime': _(u"'%s' value has the correct format "
|
'invalid_datetime': _("'%s' value has the correct format "
|
||||||
u"(YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) "
|
"(YYYY-MM-DD HH:MM[:ss[.uuuuuu]][TZ]) "
|
||||||
u"but it is an invalid date/time."),
|
"but it is an invalid date/time."),
|
||||||
}
|
}
|
||||||
empty = None
|
empty = None
|
||||||
|
|
||||||
|
@ -487,8 +490,8 @@ class DateTimeField(WritableField):
|
||||||
# local time. This won't work during DST change, but we can't
|
# local time. This won't work during DST change, but we can't
|
||||||
# do much about it, so we let the exceptions percolate up the
|
# do much about it, so we let the exceptions percolate up the
|
||||||
# call stack.
|
# call stack.
|
||||||
warnings.warn(u"DateTimeField received a naive datetime (%s)"
|
warnings.warn("DateTimeField received a naive datetime (%s)"
|
||||||
u" while time zone support is active." % value,
|
" while time zone support is active." % value,
|
||||||
RuntimeWarning)
|
RuntimeWarning)
|
||||||
default_timezone = timezone.get_default_timezone()
|
default_timezone = timezone.get_default_timezone()
|
||||||
value = timezone.make_aware(value, default_timezone)
|
value = timezone.make_aware(value, default_timezone)
|
||||||
|
|
|
@ -4,6 +4,8 @@ Basic building blocks for generic class based views.
|
||||||
We don't bind behaviour to http method handlers yet,
|
We don't bind behaviour to http method handlers yet,
|
||||||
which allows mixin classes to be composed in interesting ways.
|
which allows mixin classes to be composed in interesting ways.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.http import Http404
|
from django.http import Http404
|
||||||
from rest_framework import status
|
from rest_framework import status
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
@ -41,7 +43,7 @@ class ListModelMixin(object):
|
||||||
List a queryset.
|
List a queryset.
|
||||||
Should be mixed in with `MultipleObjectAPIView`.
|
Should be mixed in with `MultipleObjectAPIView`.
|
||||||
"""
|
"""
|
||||||
empty_error = u"Empty list and '%(class_name)s.allow_empty' is False."
|
empty_error = "Empty list and '%(class_name)s.allow_empty' is False."
|
||||||
|
|
||||||
def list(self, request, *args, **kwargs):
|
def list(self, request, *args, **kwargs):
|
||||||
queryset = self.get_queryset()
|
queryset = self.get_queryset()
|
||||||
|
|
|
@ -10,6 +10,7 @@ from django.http.multipartparser import MultiPartParser as DjangoMultiPartParser
|
||||||
from django.http.multipartparser import MultiPartParserError
|
from django.http.multipartparser import MultiPartParserError
|
||||||
from rest_framework.compat import yaml, ETParseError
|
from rest_framework.compat import yaml, ETParseError
|
||||||
from rest_framework.exceptions import ParseError
|
from rest_framework.exceptions import ParseError
|
||||||
|
from rest_framework.compat import six
|
||||||
from xml.etree import ElementTree as ET
|
from xml.etree import ElementTree as ET
|
||||||
from xml.parsers.expat import ExpatError
|
from xml.parsers.expat import ExpatError
|
||||||
import json
|
import json
|
||||||
|
@ -55,9 +56,10 @@ class JSONParser(BaseParser):
|
||||||
`files` will always be `None`.
|
`files` will always be `None`.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return json.load(stream)
|
data = stream.read().decode('iso-8859-1')
|
||||||
except ValueError, exc:
|
return json.loads(data)
|
||||||
raise ParseError('JSON parse error - %s' % unicode(exc))
|
except ValueError as exc:
|
||||||
|
raise ParseError('JSON parse error - %s' % six.text_type(exc))
|
||||||
|
|
||||||
|
|
||||||
class YAMLParser(BaseParser):
|
class YAMLParser(BaseParser):
|
||||||
|
@ -75,9 +77,10 @@ class YAMLParser(BaseParser):
|
||||||
`files` will always be `None`.
|
`files` will always be `None`.
|
||||||
"""
|
"""
|
||||||
try:
|
try:
|
||||||
return yaml.safe_load(stream)
|
data = stream.read().decode('iso-8859-1')
|
||||||
except (ValueError, yaml.parser.ParserError), exc:
|
return yaml.safe_load(data)
|
||||||
raise ParseError('YAML parse error - %s' % unicode(exc))
|
except (ValueError, yaml.parser.ParserError) as exc:
|
||||||
|
raise ParseError('YAML parse error - %s' % six.u(exc))
|
||||||
|
|
||||||
|
|
||||||
class FormParser(BaseParser):
|
class FormParser(BaseParser):
|
||||||
|
@ -121,8 +124,8 @@ class MultiPartParser(BaseParser):
|
||||||
parser = DjangoMultiPartParser(meta, stream, upload_handlers)
|
parser = DjangoMultiPartParser(meta, stream, upload_handlers)
|
||||||
data, files = parser.parse()
|
data, files = parser.parse()
|
||||||
return DataAndFiles(data, files)
|
return DataAndFiles(data, files)
|
||||||
except MultiPartParserError, exc:
|
except MultiPartParserError as exc:
|
||||||
raise ParseError('Multipart form parse error - %s' % unicode(exc))
|
raise ParseError('Multipart form parse error - %s' % six.u(exc))
|
||||||
|
|
||||||
|
|
||||||
class XMLParser(BaseParser):
|
class XMLParser(BaseParser):
|
||||||
|
@ -135,8 +138,8 @@ class XMLParser(BaseParser):
|
||||||
def parse(self, stream, media_type=None, parser_context=None):
|
def parse(self, stream, media_type=None, parser_context=None):
|
||||||
try:
|
try:
|
||||||
tree = ET.parse(stream)
|
tree = ET.parse(stream)
|
||||||
except (ExpatError, ETParseError, ValueError), exc:
|
except (ExpatError, ETParseError, ValueError) as exc:
|
||||||
raise ParseError('XML parse error - %s' % unicode(exc))
|
raise ParseError('XML parse error - %s' % six.u(exc))
|
||||||
data = self._xml_convert(tree.getroot())
|
data = self._xml_convert(tree.getroot())
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
|
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
from django.core.exceptions import ObjectDoesNotExist, ValidationError
|
||||||
from django.core.urlresolvers import resolve, get_script_prefix
|
from django.core.urlresolvers import resolve, get_script_prefix
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
from django.forms.models import ModelChoiceIterator
|
from django.forms.models import ModelChoiceIterator
|
||||||
from django.utils.encoding import smart_unicode
|
|
||||||
from django.utils.translation import ugettext_lazy as _
|
from django.utils.translation import ugettext_lazy as _
|
||||||
from rest_framework.fields import Field, WritableField
|
from rest_framework.fields import Field, WritableField
|
||||||
from rest_framework.reverse import reverse
|
from rest_framework.reverse import reverse
|
||||||
from urlparse import urlparse
|
from rest_framework.compat import urlparse
|
||||||
|
from rest_framework.compat import smart_text
|
||||||
|
|
||||||
##### Relational fields #####
|
##### Relational fields #####
|
||||||
|
|
||||||
|
@ -60,8 +63,8 @@ class RelatedField(WritableField):
|
||||||
"""
|
"""
|
||||||
Return a readable representation for use with eg. select widgets.
|
Return a readable representation for use with eg. select widgets.
|
||||||
"""
|
"""
|
||||||
desc = smart_unicode(obj)
|
desc = smart_text(obj)
|
||||||
ident = smart_unicode(self.to_native(obj))
|
ident = smart_text(self.to_native(obj))
|
||||||
if desc == ident:
|
if desc == ident:
|
||||||
return desc
|
return desc
|
||||||
return "%s - %s" % (desc, ident)
|
return "%s - %s" % (desc, ident)
|
||||||
|
@ -188,8 +191,8 @@ class PrimaryKeyRelatedField(RelatedField):
|
||||||
"""
|
"""
|
||||||
Return a readable representation for use with eg. select widgets.
|
Return a readable representation for use with eg. select widgets.
|
||||||
"""
|
"""
|
||||||
desc = smart_unicode(obj)
|
desc = smart_text(obj)
|
||||||
ident = smart_unicode(self.to_native(obj.pk))
|
ident = smart_text(self.to_native(obj.pk))
|
||||||
if desc == ident:
|
if desc == ident:
|
||||||
return desc
|
return desc
|
||||||
return "%s - %s" % (desc, ident)
|
return "%s - %s" % (desc, ident)
|
||||||
|
@ -205,7 +208,7 @@ class PrimaryKeyRelatedField(RelatedField):
|
||||||
try:
|
try:
|
||||||
return self.queryset.get(pk=data)
|
return self.queryset.get(pk=data)
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
msg = self.error_messages['does_not_exist'] % smart_unicode(data)
|
msg = self.error_messages['does_not_exist'] % smart_text(data)
|
||||||
raise ValidationError(msg)
|
raise ValidationError(msg)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
received = type(data).__name__
|
received = type(data).__name__
|
||||||
|
@ -246,8 +249,8 @@ class ManyPrimaryKeyRelatedField(ManyRelatedField):
|
||||||
"""
|
"""
|
||||||
Return a readable representation for use with eg. select widgets.
|
Return a readable representation for use with eg. select widgets.
|
||||||
"""
|
"""
|
||||||
desc = smart_unicode(obj)
|
desc = smart_text(obj)
|
||||||
ident = smart_unicode(self.to_native(obj.pk))
|
ident = smart_text(self.to_native(obj.pk))
|
||||||
if desc == ident:
|
if desc == ident:
|
||||||
return desc
|
return desc
|
||||||
return "%s - %s" % (desc, ident)
|
return "%s - %s" % (desc, ident)
|
||||||
|
@ -273,7 +276,7 @@ class ManyPrimaryKeyRelatedField(ManyRelatedField):
|
||||||
try:
|
try:
|
||||||
return self.queryset.get(pk=data)
|
return self.queryset.get(pk=data)
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
msg = self.error_messages['does_not_exist'] % smart_unicode(data)
|
msg = self.error_messages['does_not_exist'] % smart_text(data)
|
||||||
raise ValidationError(msg)
|
raise ValidationError(msg)
|
||||||
except (TypeError, ValueError):
|
except (TypeError, ValueError):
|
||||||
received = type(data).__name__
|
received = type(data).__name__
|
||||||
|
@ -404,7 +407,7 @@ class HyperlinkedRelatedField(RelatedField):
|
||||||
|
|
||||||
if http_prefix:
|
if http_prefix:
|
||||||
# If needed convert absolute URLs to relative path
|
# If needed convert absolute URLs to relative path
|
||||||
value = urlparse(value).path
|
value = urlparse.urlparse(value).path
|
||||||
prefix = get_script_prefix()
|
prefix = get_script_prefix()
|
||||||
if value.startswith(prefix):
|
if value.startswith(prefix):
|
||||||
value = '/' + value[len(prefix):]
|
value = '/' + value[len(prefix):]
|
||||||
|
|
|
@ -6,6 +6,8 @@ on the response, such as JSON encoded data or HTML output.
|
||||||
|
|
||||||
REST framework also provides an HTML renderer the renders the browsable API.
|
REST framework also provides an HTML renderer the renders the browsable API.
|
||||||
"""
|
"""
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
import string
|
import string
|
||||||
import json
|
import json
|
||||||
|
@ -60,7 +62,7 @@ class JSONRenderer(BaseRenderer):
|
||||||
if accepted_media_type:
|
if accepted_media_type:
|
||||||
# If the media type looks like 'application/json; indent=4',
|
# If the media type looks like 'application/json; indent=4',
|
||||||
# then pretty print the result.
|
# then pretty print the result.
|
||||||
base_media_type, params = parse_header(accepted_media_type)
|
base_media_type, params = parse_header(accepted_media_type.encode('ascii'))
|
||||||
indent = params.get('indent', indent)
|
indent = params.get('indent', indent)
|
||||||
try:
|
try:
|
||||||
indent = max(min(int(indent), 8), 0)
|
indent = max(min(int(indent), 8), 0)
|
||||||
|
@ -100,7 +102,7 @@ class JSONPRenderer(JSONRenderer):
|
||||||
callback = self.get_callback(renderer_context)
|
callback = self.get_callback(renderer_context)
|
||||||
json = super(JSONPRenderer, self).render(data, accepted_media_type,
|
json = super(JSONPRenderer, self).render(data, accepted_media_type,
|
||||||
renderer_context)
|
renderer_context)
|
||||||
return u"%s(%s);" % (callback, json)
|
return "%s(%s);" % (callback, json)
|
||||||
|
|
||||||
|
|
||||||
class XMLRenderer(BaseRenderer):
|
class XMLRenderer(BaseRenderer):
|
||||||
|
@ -357,7 +359,7 @@ class BrowsableAPIRenderer(BaseRenderer):
|
||||||
|
|
||||||
# Creating an on the fly form see:
|
# Creating an on the fly form see:
|
||||||
# http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python
|
# http://stackoverflow.com/questions/3915024/dynamically-creating-classes-python
|
||||||
OnTheFlyForm = type("OnTheFlyForm", (forms.Form,), fields)
|
OnTheFlyForm = type(str("OnTheFlyForm"), (forms.Form,), fields)
|
||||||
data = (obj is not None) and serializer.data or None
|
data = (obj is not None) and serializer.data or None
|
||||||
form_instance = OnTheFlyForm(data)
|
form_instance = OnTheFlyForm(data)
|
||||||
return form_instance
|
return form_instance
|
||||||
|
|
|
@ -9,7 +9,7 @@ The wrapped request then offers a richer API, in particular :
|
||||||
- full support of PUT method, including support for file uploads
|
- full support of PUT method, including support for file uploads
|
||||||
- form overloading of HTTP method, content type and content
|
- form overloading of HTTP method, content type and content
|
||||||
"""
|
"""
|
||||||
from StringIO import StringIO
|
from rest_framework.compat import BytesIO
|
||||||
|
|
||||||
from django.http.multipartparser import parse_header
|
from django.http.multipartparser import parse_header
|
||||||
from rest_framework import exceptions
|
from rest_framework import exceptions
|
||||||
|
@ -20,7 +20,7 @@ def is_form_media_type(media_type):
|
||||||
"""
|
"""
|
||||||
Return True if the media type is a valid form media type.
|
Return True if the media type is a valid form media type.
|
||||||
"""
|
"""
|
||||||
base_media_type, params = parse_header(media_type)
|
base_media_type, params = parse_header(media_type.encode('iso-8859-1'))
|
||||||
return (base_media_type == 'application/x-www-form-urlencoded' or
|
return (base_media_type == 'application/x-www-form-urlencoded' or
|
||||||
base_media_type == 'multipart/form-data')
|
base_media_type == 'multipart/form-data')
|
||||||
|
|
||||||
|
@ -242,7 +242,7 @@ class Request(object):
|
||||||
elif hasattr(self._request, 'read'):
|
elif hasattr(self._request, 'read'):
|
||||||
self._stream = self._request
|
self._stream = self._request
|
||||||
else:
|
else:
|
||||||
self._stream = StringIO(self.raw_post_data)
|
self._stream = BytesIO(self.raw_post_data)
|
||||||
|
|
||||||
def _perform_form_overloading(self):
|
def _perform_form_overloading(self):
|
||||||
"""
|
"""
|
||||||
|
@ -277,7 +277,7 @@ class Request(object):
|
||||||
self._CONTENT_PARAM in self._data and
|
self._CONTENT_PARAM in self._data and
|
||||||
self._CONTENTTYPE_PARAM in self._data):
|
self._CONTENTTYPE_PARAM in self._data):
|
||||||
self._content_type = self._data[self._CONTENTTYPE_PARAM]
|
self._content_type = self._data[self._CONTENTTYPE_PARAM]
|
||||||
self._stream = StringIO(self._data[self._CONTENT_PARAM])
|
self._stream = BytesIO(self._data[self._CONTENT_PARAM].encode('iso-8859-1'))
|
||||||
self._data, self._files = (Empty, Empty)
|
self._data, self._files = (Empty, Empty)
|
||||||
|
|
||||||
def _parse(self):
|
def _parse(self):
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
from django.core.handlers.wsgi import STATUS_CODE_TEXT
|
from django.core.handlers.wsgi import STATUS_CODE_TEXT
|
||||||
from django.template.response import SimpleTemplateResponse
|
from django.template.response import SimpleTemplateResponse
|
||||||
|
|
||||||
|
from rest_framework.compat import six
|
||||||
|
|
||||||
|
|
||||||
class Response(SimpleTemplateResponse):
|
class Response(SimpleTemplateResponse):
|
||||||
"""
|
"""
|
||||||
|
@ -22,9 +24,9 @@ class Response(SimpleTemplateResponse):
|
||||||
self.data = data
|
self.data = data
|
||||||
self.template_name = template_name
|
self.template_name = template_name
|
||||||
self.exception = exception
|
self.exception = exception
|
||||||
|
|
||||||
if headers:
|
if headers:
|
||||||
for name,value in headers.iteritems():
|
for name, value in six.iteritems(headers):
|
||||||
self[name] = value
|
self[name] = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
|
@ -33,7 +33,7 @@ def main():
|
||||||
elif len(sys.argv) == 1:
|
elif len(sys.argv) == 1:
|
||||||
test_case = ''
|
test_case = ''
|
||||||
else:
|
else:
|
||||||
print usage()
|
print(usage())
|
||||||
sys.exit(1)
|
sys.exit(1)
|
||||||
failures = test_runner.run_tests(['tests' + test_case])
|
failures = test_runner.run_tests(['tests' + test_case])
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ from django.db import models
|
||||||
from django.forms import widgets
|
from django.forms import widgets
|
||||||
from django.utils.datastructures import SortedDict
|
from django.utils.datastructures import SortedDict
|
||||||
from rest_framework.compat import get_concrete_model
|
from rest_framework.compat import get_concrete_model
|
||||||
|
from rest_framework.compat import six
|
||||||
|
|
||||||
# Note: We do the following so that users of the framework can use this style:
|
# Note: We do the following so that users of the framework can use this style:
|
||||||
#
|
#
|
||||||
|
@ -64,7 +65,7 @@ def _get_declared_fields(bases, attrs):
|
||||||
Note that all fields from the base classes are used.
|
Note that all fields from the base classes are used.
|
||||||
"""
|
"""
|
||||||
fields = [(field_name, attrs.pop(field_name))
|
fields = [(field_name, attrs.pop(field_name))
|
||||||
for field_name, obj in attrs.items()
|
for field_name, obj in list(six.iteritems(attrs))
|
||||||
if isinstance(obj, Field)]
|
if isinstance(obj, Field)]
|
||||||
fields.sort(key=lambda x: x[1].creation_counter)
|
fields.sort(key=lambda x: x[1].creation_counter)
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ def _get_declared_fields(bases, attrs):
|
||||||
# in order to maintain the correct order of fields.
|
# in order to maintain the correct order of fields.
|
||||||
for base in bases[::-1]:
|
for base in bases[::-1]:
|
||||||
if hasattr(base, 'base_fields'):
|
if hasattr(base, 'base_fields'):
|
||||||
fields = base.base_fields.items() + fields
|
fields = list(base.base_fields.items()) + fields
|
||||||
|
|
||||||
return SortedDict(fields)
|
return SortedDict(fields)
|
||||||
|
|
||||||
|
@ -359,8 +360,8 @@ class BaseSerializer(Field):
|
||||||
return self.object
|
return self.object
|
||||||
|
|
||||||
|
|
||||||
class Serializer(BaseSerializer):
|
class Serializer(six.with_metaclass(SerializerMetaclass, BaseSerializer)):
|
||||||
__metaclass__ = SerializerMetaclass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class ModelSerializerOptions(SerializerOptions):
|
class ModelSerializerOptions(SerializerOptions):
|
||||||
|
@ -560,6 +561,12 @@ class ModelSerializer(Serializer):
|
||||||
else:
|
else:
|
||||||
instance = self.opts.model(**attrs)
|
instance = self.opts.model(**attrs)
|
||||||
|
|
||||||
|
try:
|
||||||
|
instance.full_clean(exclude=self.get_validation_exclusions())
|
||||||
|
except ValidationError as err:
|
||||||
|
self._errors = err.message_dict
|
||||||
|
return None
|
||||||
|
|
||||||
return instance
|
return instance
|
||||||
|
|
||||||
def from_native(self, data, files):
|
def from_native(self, data, files):
|
||||||
|
|
|
@ -19,6 +19,7 @@ back to the defaults.
|
||||||
"""
|
"""
|
||||||
from django.conf import settings
|
from django.conf import settings
|
||||||
from django.utils import importlib
|
from django.utils import importlib
|
||||||
|
from rest_framework.compat import six
|
||||||
|
|
||||||
|
|
||||||
USER_SETTINGS = getattr(settings, 'REST_FRAMEWORK', None)
|
USER_SETTINGS = getattr(settings, 'REST_FRAMEWORK', None)
|
||||||
|
@ -74,6 +75,9 @@ DEFAULTS = {
|
||||||
'URL_FORMAT_OVERRIDE': 'format',
|
'URL_FORMAT_OVERRIDE': 'format',
|
||||||
|
|
||||||
'FORMAT_SUFFIX_KWARG': 'format',
|
'FORMAT_SUFFIX_KWARG': 'format',
|
||||||
|
|
||||||
|
# Header encoding (see RFC5987)
|
||||||
|
'HTTP_HEADER_ENCODING': 'iso-8859-1',
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -98,7 +102,7 @@ def perform_import(val, setting_name):
|
||||||
If the given setting is a string import notation,
|
If the given setting is a string import notation,
|
||||||
then perform the necessary import or imports.
|
then perform the necessary import or imports.
|
||||||
"""
|
"""
|
||||||
if isinstance(val, basestring):
|
if isinstance(val, six.string_types):
|
||||||
return import_from_string(val, setting_name)
|
return import_from_string(val, setting_name)
|
||||||
elif isinstance(val, (list, tuple)):
|
elif isinstance(val, (list, tuple)):
|
||||||
return [import_from_string(item, setting_name) for item in val]
|
return [import_from_string(item, setting_name) for item in val]
|
||||||
|
|
|
@ -1,10 +1,14 @@
|
||||||
|
from __future__ import unicode_literals, absolute_import
|
||||||
|
|
||||||
from django import template
|
from django import template
|
||||||
from django.core.urlresolvers import reverse
|
from django.core.urlresolvers import reverse
|
||||||
from django.http import QueryDict
|
from django.http import QueryDict
|
||||||
from django.utils.encoding import force_unicode
|
|
||||||
from django.utils.html import escape
|
from django.utils.html import escape
|
||||||
from django.utils.safestring import SafeData, mark_safe
|
from django.utils.safestring import SafeData, mark_safe
|
||||||
from urlparse import urlsplit, urlunsplit
|
from rest_framework.compat import urlparse
|
||||||
|
from rest_framework.compat import force_text
|
||||||
|
from rest_framework.compat import six
|
||||||
|
|
||||||
import re
|
import re
|
||||||
import string
|
import string
|
||||||
|
|
||||||
|
@ -99,11 +103,11 @@ def replace_query_param(url, key, val):
|
||||||
Given a URL and a key/val pair, set or replace an item in the query
|
Given a URL and a key/val pair, set or replace an item in the query
|
||||||
parameters of the URL, and return the new URL.
|
parameters of the URL, and return the new URL.
|
||||||
"""
|
"""
|
||||||
(scheme, netloc, path, query, fragment) = urlsplit(url)
|
(scheme, netloc, path, query, fragment) = urlparse.urlsplit(url)
|
||||||
query_dict = QueryDict(query).copy()
|
query_dict = QueryDict(query).copy()
|
||||||
query_dict[key] = val
|
query_dict[key] = val
|
||||||
query = query_dict.urlencode()
|
query = query_dict.urlencode()
|
||||||
return urlunsplit((scheme, netloc, path, query, fragment))
|
return urlparse.urlunsplit((scheme, netloc, path, query, fragment))
|
||||||
|
|
||||||
|
|
||||||
# Regex for adding classes to html snippets
|
# Regex for adding classes to html snippets
|
||||||
|
@ -179,7 +183,7 @@ def add_class(value, css_class):
|
||||||
In the case of REST Framework, the filter is used to add Bootstrap-specific
|
In the case of REST Framework, the filter is used to add Bootstrap-specific
|
||||||
classes to the forms.
|
classes to the forms.
|
||||||
"""
|
"""
|
||||||
html = unicode(value)
|
html = six.text_type(value)
|
||||||
match = class_re.search(html)
|
match = class_re.search(html)
|
||||||
if match:
|
if match:
|
||||||
m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class,
|
m = re.search(r'^%s$|^%s\s|\s%s\s|\s%s$' % (css_class, css_class,
|
||||||
|
@ -213,7 +217,7 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru
|
||||||
"""
|
"""
|
||||||
trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
|
trim_url = lambda x, limit=trim_url_limit: limit is not None and (len(x) > limit and ('%s...' % x[:max(0, limit - 3)])) or x
|
||||||
safe_input = isinstance(text, SafeData)
|
safe_input = isinstance(text, SafeData)
|
||||||
words = word_split_re.split(force_unicode(text))
|
words = word_split_re.split(force_text(text))
|
||||||
nofollow_attr = nofollow and ' rel="nofollow"' or ''
|
nofollow_attr = nofollow and ' rel="nofollow"' or ''
|
||||||
for i, word in enumerate(words):
|
for i, word in enumerate(words):
|
||||||
match = None
|
match = None
|
||||||
|
@ -249,4 +253,4 @@ def urlize_quoted_links(text, trim_url_limit=None, nofollow=True, autoescape=Tru
|
||||||
words[i] = mark_safe(word)
|
words[i] = mark_safe(word)
|
||||||
elif autoescape:
|
elif autoescape:
|
||||||
words[i] = escape(word)
|
words[i] = escape(word)
|
||||||
return mark_safe(u''.join(words))
|
return mark_safe(''.join(words))
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
from django.contrib.auth.models import User
|
from django.contrib.auth.models import User
|
||||||
from django.http import HttpResponse
|
from django.http import HttpResponse
|
||||||
from django.test import Client, TestCase
|
from django.test import Client, TestCase
|
||||||
|
|
||||||
from rest_framework import permissions
|
from rest_framework import permissions
|
||||||
from rest_framework.authtoken.models import Token
|
from rest_framework.authtoken.models import Token
|
||||||
from rest_framework.authentication import TokenAuthentication, BasicAuthentication, SessionAuthentication
|
from rest_framework.authentication import TokenAuthentication, BasicAuthentication, SessionAuthentication
|
||||||
|
@ -42,13 +41,13 @@ class BasicAuthTests(TestCase):
|
||||||
|
|
||||||
def test_post_form_passing_basic_auth(self):
|
def test_post_form_passing_basic_auth(self):
|
||||||
"""Ensure POSTing json over basic auth with correct credentials passes and does not require CSRF"""
|
"""Ensure POSTing json over basic auth with correct credentials passes and does not require CSRF"""
|
||||||
auth = 'Basic %s' % base64.encodestring('%s:%s' % (self.username, self.password)).strip()
|
auth = 'Basic %s' % base64.encodestring('%s:%s' % (self.username, self.password)).encode('iso-8859-1').strip().decode('iso-8859-1')
|
||||||
response = self.csrf_client.post('/basic/', {'example': 'example'}, HTTP_AUTHORIZATION=auth)
|
response = self.csrf_client.post('/basic/', {'example': 'example'}, HTTP_AUTHORIZATION=auth)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
def test_post_json_passing_basic_auth(self):
|
def test_post_json_passing_basic_auth(self):
|
||||||
"""Ensure POSTing form over basic auth with correct credentials passes and does not require CSRF"""
|
"""Ensure POSTing form over basic auth with correct credentials passes and does not require CSRF"""
|
||||||
auth = 'Basic %s' % base64.encodestring('%s:%s' % (self.username, self.password)).strip()
|
auth = 'Basic %s' % base64.encodestring('%s:%s' % (self.username, self.password)).encode('iso-8859-1').strip().decode('iso-8859-1')
|
||||||
response = self.csrf_client.post('/basic/', json.dumps({'example': 'example'}), 'application/json', HTTP_AUTHORIZATION=auth)
|
response = self.csrf_client.post('/basic/', json.dumps({'example': 'example'}), 'application/json', HTTP_AUTHORIZATION=auth)
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
|
|
||||||
|
@ -159,7 +158,7 @@ class TokenAuthTests(TestCase):
|
||||||
response = client.post('/auth-token/',
|
response = client.post('/auth-token/',
|
||||||
json.dumps({'username': self.username, 'password': self.password}), 'application/json')
|
json.dumps({'username': self.username, 'password': self.password}), 'application/json')
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(json.loads(response.content)['token'], self.key)
|
self.assertEqual(json.loads(response.content.decode('ascii'))['token'], self.key)
|
||||||
|
|
||||||
def test_token_login_json_bad_creds(self):
|
def test_token_login_json_bad_creds(self):
|
||||||
"""Ensure token login view using JSON POST fails if bad credentials are used."""
|
"""Ensure token login view using JSON POST fails if bad credentials are used."""
|
||||||
|
@ -181,4 +180,4 @@ class TokenAuthTests(TestCase):
|
||||||
response = client.post('/auth-token/',
|
response = client.post('/auth-token/',
|
||||||
{'username': self.username, 'password': self.password})
|
{'username': self.username, 'password': self.password})
|
||||||
self.assertEqual(response.status_code, 200)
|
self.assertEqual(response.status_code, 200)
|
||||||
self.assertEqual(json.loads(response.content)['token'], self.key)
|
self.assertEqual(json.loads(response.content.decode('ascii'))['token'], self.key)
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import StringIO
|
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
from rest_framework.compat import BytesIO
|
||||||
|
from rest_framework.compat import six
|
||||||
|
|
||||||
|
|
||||||
class UploadedFile(object):
|
class UploadedFile(object):
|
||||||
|
@ -27,9 +28,9 @@ class UploadedFileSerializer(serializers.Serializer):
|
||||||
class FileSerializerTests(TestCase):
|
class FileSerializerTests(TestCase):
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
file = StringIO.StringIO('stuff')
|
file = BytesIO(six.b('stuff'))
|
||||||
file.name = 'stuff.txt'
|
file.name = 'stuff.txt'
|
||||||
file.size = file.len
|
file.size = len(file.getvalue())
|
||||||
serializer = UploadedFileSerializer(data={'created': now}, files={'file': file})
|
serializer = UploadedFileSerializer(data={'created': now}, files={'file': file})
|
||||||
uploaded_file = UploadedFile(file=file, created=now)
|
uploaded_file = UploadedFile(file=file, created=now)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.contrib.contenttypes.models import ContentType
|
from django.contrib.contenttypes.models import ContentType
|
||||||
from django.contrib.contenttypes.generic import GenericRelation, GenericForeignKey
|
from django.contrib.contenttypes.generic import GenericRelation, GenericForeignKey
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
@ -63,8 +65,8 @@ class TestGenericRelations(TestCase):
|
||||||
|
|
||||||
serializer = BookmarkSerializer(self.bookmark)
|
serializer = BookmarkSerializer(self.bookmark)
|
||||||
expected = {
|
expected = {
|
||||||
'tags': [u'django', u'python'],
|
'tags': ['django', 'python'],
|
||||||
'url': u'https://www.djangoproject.com/'
|
'url': 'https://www.djangoproject.com/'
|
||||||
}
|
}
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
import json
|
from __future__ import unicode_literals
|
||||||
from django.db import models
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework import generics, serializers, status
|
from rest_framework import generics, serializers, status
|
||||||
from rest_framework.tests.utils import RequestFactory
|
from rest_framework.tests.utils import RequestFactory
|
||||||
from rest_framework.tests.models import BasicModel, Comment, SlugBasedModel
|
from rest_framework.tests.models import BasicModel, Comment, SlugBasedModel
|
||||||
|
from rest_framework.compat import six
|
||||||
|
import json
|
||||||
|
|
||||||
factory = RequestFactory()
|
factory = RequestFactory()
|
||||||
|
|
||||||
|
@ -72,7 +73,7 @@ class TestRootView(TestCase):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
response = self.view(request).render()
|
response = self.view(request).render()
|
||||||
self.assertEquals(response.status_code, status.HTTP_201_CREATED)
|
self.assertEquals(response.status_code, status.HTTP_201_CREATED)
|
||||||
self.assertEquals(response.data, {'id': 4, 'text': u'foobar'})
|
self.assertEquals(response.data, {'id': 4, 'text': 'foobar'})
|
||||||
created = self.objects.get(id=4)
|
created = self.objects.get(id=4)
|
||||||
self.assertEquals(created.text, 'foobar')
|
self.assertEquals(created.text, 'foobar')
|
||||||
|
|
||||||
|
@ -127,7 +128,7 @@ class TestRootView(TestCase):
|
||||||
content_type='application/json')
|
content_type='application/json')
|
||||||
response = self.view(request).render()
|
response = self.view(request).render()
|
||||||
self.assertEquals(response.status_code, status.HTTP_201_CREATED)
|
self.assertEquals(response.status_code, status.HTTP_201_CREATED)
|
||||||
self.assertEquals(response.data, {'id': 4, 'text': u'foobar'})
|
self.assertEquals(response.data, {'id': 4, 'text': 'foobar'})
|
||||||
created = self.objects.get(id=4)
|
created = self.objects.get(id=4)
|
||||||
self.assertEquals(created.text, 'foobar')
|
self.assertEquals(created.text, 'foobar')
|
||||||
|
|
||||||
|
@ -202,7 +203,7 @@ class TestInstanceView(TestCase):
|
||||||
request = factory.delete('/1')
|
request = factory.delete('/1')
|
||||||
response = self.view(request, pk=1).render()
|
response = self.view(request, pk=1).render()
|
||||||
self.assertEquals(response.status_code, status.HTTP_204_NO_CONTENT)
|
self.assertEquals(response.status_code, status.HTTP_204_NO_CONTENT)
|
||||||
self.assertEquals(response.content, '')
|
self.assertEquals(response.content, six.b(''))
|
||||||
ids = [obj.id for obj in self.objects.all()]
|
ids = [obj.id for obj in self.objects.all()]
|
||||||
self.assertEquals(ids, [2, 3])
|
self.assertEquals(ids, [2, 3])
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@ from rest_framework.compat import patterns, url
|
||||||
from rest_framework.decorators import api_view, renderer_classes
|
from rest_framework.decorators import api_view, renderer_classes
|
||||||
from rest_framework.renderers import TemplateHTMLRenderer
|
from rest_framework.renderers import TemplateHTMLRenderer
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
|
from rest_framework.compat import six
|
||||||
|
|
||||||
|
|
||||||
@api_view(('GET',))
|
@api_view(('GET',))
|
||||||
|
@ -68,13 +69,13 @@ class TemplateHTMLRendererTests(TestCase):
|
||||||
def test_not_found_html_view(self):
|
def test_not_found_html_view(self):
|
||||||
response = self.client.get('/not_found')
|
response = self.client.get('/not_found')
|
||||||
self.assertEquals(response.status_code, 404)
|
self.assertEquals(response.status_code, 404)
|
||||||
self.assertEquals(response.content, "404 Not Found")
|
self.assertEquals(response.content, six.b("404 Not Found"))
|
||||||
self.assertEquals(response['Content-Type'], 'text/html')
|
self.assertEquals(response['Content-Type'], 'text/html')
|
||||||
|
|
||||||
def test_permission_denied_html_view(self):
|
def test_permission_denied_html_view(self):
|
||||||
response = self.client.get('/permission_denied')
|
response = self.client.get('/permission_denied')
|
||||||
self.assertEquals(response.status_code, 403)
|
self.assertEquals(response.status_code, 403)
|
||||||
self.assertEquals(response.content, "403 Forbidden")
|
self.assertEquals(response.content, six.b("403 Forbidden"))
|
||||||
self.assertEquals(response['Content-Type'], 'text/html')
|
self.assertEquals(response['Content-Type'], 'text/html')
|
||||||
|
|
||||||
|
|
||||||
|
@ -105,11 +106,11 @@ class TemplateHTMLRendererExceptionTests(TestCase):
|
||||||
def test_not_found_html_view_with_template(self):
|
def test_not_found_html_view_with_template(self):
|
||||||
response = self.client.get('/not_found')
|
response = self.client.get('/not_found')
|
||||||
self.assertEquals(response.status_code, 404)
|
self.assertEquals(response.status_code, 404)
|
||||||
self.assertEquals(response.content, "404: Not found")
|
self.assertEquals(response.content, six.b("404: Not found"))
|
||||||
self.assertEquals(response['Content-Type'], 'text/html')
|
self.assertEquals(response['Content-Type'], 'text/html')
|
||||||
|
|
||||||
def test_permission_denied_html_view_with_template(self):
|
def test_permission_denied_html_view_with_template(self):
|
||||||
response = self.client.get('/permission_denied')
|
response = self.client.get('/permission_denied')
|
||||||
self.assertEquals(response.status_code, 403)
|
self.assertEquals(response.status_code, 403)
|
||||||
self.assertEquals(response.content, "403: Permission denied")
|
self.assertEquals(response.content, six.b("403: Permission denied"))
|
||||||
self.assertEquals(response['Content-Type'], 'text/html')
|
self.assertEquals(response['Content-Type'], 'text/html')
|
||||||
|
|
|
@ -131,7 +131,7 @@
|
||||||
# self.assertEqual(data['key1'], 'val1')
|
# self.assertEqual(data['key1'], 'val1')
|
||||||
# self.assertEqual(files['file1'].read(), 'blablabla')
|
# self.assertEqual(files['file1'].read(), 'blablabla')
|
||||||
|
|
||||||
from StringIO import StringIO
|
from rest_framework.compat import StringIO
|
||||||
from django import forms
|
from django import forms
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework.parsers import FormParser
|
from rest_framework.parsers import FormParser
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.compat import patterns, url
|
from rest_framework.compat import patterns, url
|
||||||
|
@ -74,9 +76,9 @@ class HyperlinkedManyToManyTests(TestCase):
|
||||||
queryset = ManyToManySource.objects.all()
|
queryset = ManyToManySource.objects.all()
|
||||||
serializer = ManyToManySourceSerializer(queryset)
|
serializer = ManyToManySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/']},
|
{'url': '/manytomanysource/1/', 'name': 'source-1', 'targets': ['/manytomanytarget/1/']},
|
||||||
{'url': '/manytomanysource/2/', 'name': u'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']},
|
{'url': '/manytomanysource/2/', 'name': 'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']},
|
||||||
{'url': '/manytomanysource/3/', 'name': u'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}
|
{'url': '/manytomanysource/3/', 'name': 'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -84,14 +86,14 @@ class HyperlinkedManyToManyTests(TestCase):
|
||||||
queryset = ManyToManyTarget.objects.all()
|
queryset = ManyToManyTarget.objects.all()
|
||||||
serializer = ManyToManyTargetSerializer(queryset)
|
serializer = ManyToManyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/manytomanytarget/1/', 'name': u'target-1', 'sources': ['/manytomanysource/1/', '/manytomanysource/2/', '/manytomanysource/3/']},
|
{'url': '/manytomanytarget/1/', 'name': 'target-1', 'sources': ['/manytomanysource/1/', '/manytomanysource/2/', '/manytomanysource/3/']},
|
||||||
{'url': '/manytomanytarget/2/', 'name': u'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']},
|
{'url': '/manytomanytarget/2/', 'name': 'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']},
|
||||||
{'url': '/manytomanytarget/3/', 'name': u'target-3', 'sources': ['/manytomanysource/3/']}
|
{'url': '/manytomanytarget/3/', 'name': 'target-3', 'sources': ['/manytomanysource/3/']}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_many_to_many_update(self):
|
def test_many_to_many_update(self):
|
||||||
data = {'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}
|
data = {'url': '/manytomanysource/1/', 'name': 'source-1', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}
|
||||||
instance = ManyToManySource.objects.get(pk=1)
|
instance = ManyToManySource.objects.get(pk=1)
|
||||||
serializer = ManyToManySourceSerializer(instance, data=data)
|
serializer = ManyToManySourceSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -102,14 +104,14 @@ class HyperlinkedManyToManyTests(TestCase):
|
||||||
queryset = ManyToManySource.objects.all()
|
queryset = ManyToManySource.objects.all()
|
||||||
serializer = ManyToManySourceSerializer(queryset)
|
serializer = ManyToManySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']},
|
{'url': '/manytomanysource/1/', 'name': 'source-1', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']},
|
||||||
{'url': '/manytomanysource/2/', 'name': u'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']},
|
{'url': '/manytomanysource/2/', 'name': 'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']},
|
||||||
{'url': '/manytomanysource/3/', 'name': u'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}
|
{'url': '/manytomanysource/3/', 'name': 'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_reverse_many_to_many_update(self):
|
def test_reverse_many_to_many_update(self):
|
||||||
data = {'url': '/manytomanytarget/1/', 'name': u'target-1', 'sources': ['/manytomanysource/1/']}
|
data = {'url': '/manytomanytarget/1/', 'name': 'target-1', 'sources': ['/manytomanysource/1/']}
|
||||||
instance = ManyToManyTarget.objects.get(pk=1)
|
instance = ManyToManyTarget.objects.get(pk=1)
|
||||||
serializer = ManyToManyTargetSerializer(instance, data=data)
|
serializer = ManyToManyTargetSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -120,48 +122,48 @@ class HyperlinkedManyToManyTests(TestCase):
|
||||||
queryset = ManyToManyTarget.objects.all()
|
queryset = ManyToManyTarget.objects.all()
|
||||||
serializer = ManyToManyTargetSerializer(queryset)
|
serializer = ManyToManyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/manytomanytarget/1/', 'name': u'target-1', 'sources': ['/manytomanysource/1/']},
|
{'url': '/manytomanytarget/1/', 'name': 'target-1', 'sources': ['/manytomanysource/1/']},
|
||||||
{'url': '/manytomanytarget/2/', 'name': u'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']},
|
{'url': '/manytomanytarget/2/', 'name': 'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']},
|
||||||
{'url': '/manytomanytarget/3/', 'name': u'target-3', 'sources': ['/manytomanysource/3/']}
|
{'url': '/manytomanytarget/3/', 'name': 'target-3', 'sources': ['/manytomanysource/3/']}
|
||||||
|
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_many_to_many_create(self):
|
def test_many_to_many_create(self):
|
||||||
data = {'url': '/manytomanysource/4/', 'name': u'source-4', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/3/']}
|
data = {'url': '/manytomanysource/4/', 'name': 'source-4', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/3/']}
|
||||||
serializer = ManyToManySourceSerializer(data=data)
|
serializer = ManyToManySourceSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'source-4')
|
self.assertEqual(obj.name, 'source-4')
|
||||||
|
|
||||||
# Ensure source 4 is added, and everything else is as expected
|
# Ensure source 4 is added, and everything else is as expected
|
||||||
queryset = ManyToManySource.objects.all()
|
queryset = ManyToManySource.objects.all()
|
||||||
serializer = ManyToManySourceSerializer(queryset)
|
serializer = ManyToManySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/manytomanysource/1/', 'name': u'source-1', 'targets': ['/manytomanytarget/1/']},
|
{'url': '/manytomanysource/1/', 'name': 'source-1', 'targets': ['/manytomanytarget/1/']},
|
||||||
{'url': '/manytomanysource/2/', 'name': u'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']},
|
{'url': '/manytomanysource/2/', 'name': 'source-2', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/']},
|
||||||
{'url': '/manytomanysource/3/', 'name': u'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']},
|
{'url': '/manytomanysource/3/', 'name': 'source-3', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/2/', '/manytomanytarget/3/']},
|
||||||
{'url': '/manytomanysource/4/', 'name': u'source-4', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/3/']}
|
{'url': '/manytomanysource/4/', 'name': 'source-4', 'targets': ['/manytomanytarget/1/', '/manytomanytarget/3/']}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_reverse_many_to_many_create(self):
|
def test_reverse_many_to_many_create(self):
|
||||||
data = {'url': '/manytomanytarget/4/', 'name': u'target-4', 'sources': ['/manytomanysource/1/', '/manytomanysource/3/']}
|
data = {'url': '/manytomanytarget/4/', 'name': 'target-4', 'sources': ['/manytomanysource/1/', '/manytomanysource/3/']}
|
||||||
serializer = ManyToManyTargetSerializer(data=data)
|
serializer = ManyToManyTargetSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'target-4')
|
self.assertEqual(obj.name, 'target-4')
|
||||||
|
|
||||||
# Ensure target 4 is added, and everything else is as expected
|
# Ensure target 4 is added, and everything else is as expected
|
||||||
queryset = ManyToManyTarget.objects.all()
|
queryset = ManyToManyTarget.objects.all()
|
||||||
serializer = ManyToManyTargetSerializer(queryset)
|
serializer = ManyToManyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/manytomanytarget/1/', 'name': u'target-1', 'sources': ['/manytomanysource/1/', '/manytomanysource/2/', '/manytomanysource/3/']},
|
{'url': '/manytomanytarget/1/', 'name': 'target-1', 'sources': ['/manytomanysource/1/', '/manytomanysource/2/', '/manytomanysource/3/']},
|
||||||
{'url': '/manytomanytarget/2/', 'name': u'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']},
|
{'url': '/manytomanytarget/2/', 'name': 'target-2', 'sources': ['/manytomanysource/2/', '/manytomanysource/3/']},
|
||||||
{'url': '/manytomanytarget/3/', 'name': u'target-3', 'sources': ['/manytomanysource/3/']},
|
{'url': '/manytomanytarget/3/', 'name': 'target-3', 'sources': ['/manytomanysource/3/']},
|
||||||
{'url': '/manytomanytarget/4/', 'name': u'target-4', 'sources': ['/manytomanysource/1/', '/manytomanysource/3/']}
|
{'url': '/manytomanytarget/4/', 'name': 'target-4', 'sources': ['/manytomanysource/1/', '/manytomanysource/3/']}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -182,9 +184,9 @@ class HyperlinkedForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeySource.objects.all()
|
queryset = ForeignKeySource.objects.all()
|
||||||
serializer = ForeignKeySourceSerializer(queryset)
|
serializer = ForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/foreignkeysource/1/', 'name': u'source-1', 'target': '/foreignkeytarget/1/'},
|
{'url': '/foreignkeysource/1/', 'name': 'source-1', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/foreignkeysource/2/', 'name': u'source-2', 'target': '/foreignkeytarget/1/'},
|
{'url': '/foreignkeysource/2/', 'name': 'source-2', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/foreignkeysource/3/', 'name': u'source-3', 'target': '/foreignkeytarget/1/'}
|
{'url': '/foreignkeysource/3/', 'name': 'source-3', 'target': '/foreignkeytarget/1/'}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -192,13 +194,13 @@ class HyperlinkedForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
serializer = ForeignKeyTargetSerializer(queryset)
|
serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/foreignkeytarget/1/', 'name': u'target-1', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/2/', '/foreignkeysource/3/']},
|
{'url': '/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/2/', '/foreignkeysource/3/']},
|
||||||
{'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': []},
|
{'url': '/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_update(self):
|
def test_foreign_key_update(self):
|
||||||
data = {'url': '/foreignkeysource/1/', 'name': u'source-1', 'target': '/foreignkeytarget/2/'}
|
data = {'url': '/foreignkeysource/1/', 'name': 'source-1', 'target': '/foreignkeytarget/2/'}
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
serializer = ForeignKeySourceSerializer(instance, data=data)
|
serializer = ForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -209,9 +211,9 @@ class HyperlinkedForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeySource.objects.all()
|
queryset = ForeignKeySource.objects.all()
|
||||||
serializer = ForeignKeySourceSerializer(queryset)
|
serializer = ForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/foreignkeysource/1/', 'name': u'source-1', 'target': '/foreignkeytarget/2/'},
|
{'url': '/foreignkeysource/1/', 'name': 'source-1', 'target': '/foreignkeytarget/2/'},
|
||||||
{'url': '/foreignkeysource/2/', 'name': u'source-2', 'target': '/foreignkeytarget/1/'},
|
{'url': '/foreignkeysource/2/', 'name': 'source-2', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/foreignkeysource/3/', 'name': u'source-3', 'target': '/foreignkeytarget/1/'}
|
{'url': '/foreignkeysource/3/', 'name': 'source-3', 'target': '/foreignkeytarget/1/'}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -223,7 +225,7 @@ class HyperlinkedForeignKeyTests(TestCase):
|
||||||
self.assertEquals(serializer.errors, {'target': [u'Incorrect type. Expected url string, received int.']})
|
self.assertEquals(serializer.errors, {'target': [u'Incorrect type. Expected url string, received int.']})
|
||||||
|
|
||||||
def test_reverse_foreign_key_update(self):
|
def test_reverse_foreign_key_update(self):
|
||||||
data = {'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}
|
data = {'url': '/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}
|
||||||
instance = ForeignKeyTarget.objects.get(pk=2)
|
instance = ForeignKeyTarget.objects.get(pk=2)
|
||||||
serializer = ForeignKeyTargetSerializer(instance, data=data)
|
serializer = ForeignKeyTargetSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -232,8 +234,8 @@ class HyperlinkedForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
new_serializer = ForeignKeyTargetSerializer(queryset)
|
new_serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/foreignkeytarget/1/', 'name': u'target-1', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/2/', '/foreignkeysource/3/']},
|
{'url': '/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/2/', '/foreignkeysource/3/']},
|
||||||
{'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': []},
|
{'url': '/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
|
||||||
]
|
]
|
||||||
self.assertEquals(new_serializer.data, expected)
|
self.assertEquals(new_serializer.data, expected)
|
||||||
|
|
||||||
|
@ -244,54 +246,54 @@ class HyperlinkedForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
serializer = ForeignKeyTargetSerializer(queryset)
|
serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/foreignkeytarget/1/', 'name': u'target-1', 'sources': ['/foreignkeysource/2/']},
|
{'url': '/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['/foreignkeysource/2/']},
|
||||||
{'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']},
|
{'url': '/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_create(self):
|
def test_foreign_key_create(self):
|
||||||
data = {'url': '/foreignkeysource/4/', 'name': u'source-4', 'target': '/foreignkeytarget/2/'}
|
data = {'url': '/foreignkeysource/4/', 'name': 'source-4', 'target': '/foreignkeytarget/2/'}
|
||||||
serializer = ForeignKeySourceSerializer(data=data)
|
serializer = ForeignKeySourceSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'source-4')
|
self.assertEqual(obj.name, 'source-4')
|
||||||
|
|
||||||
# Ensure source 1 is updated, and everything else is as expected
|
# Ensure source 1 is updated, and everything else is as expected
|
||||||
queryset = ForeignKeySource.objects.all()
|
queryset = ForeignKeySource.objects.all()
|
||||||
serializer = ForeignKeySourceSerializer(queryset)
|
serializer = ForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/foreignkeysource/1/', 'name': u'source-1', 'target': '/foreignkeytarget/1/'},
|
{'url': '/foreignkeysource/1/', 'name': 'source-1', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/foreignkeysource/2/', 'name': u'source-2', 'target': '/foreignkeytarget/1/'},
|
{'url': '/foreignkeysource/2/', 'name': 'source-2', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/foreignkeysource/3/', 'name': u'source-3', 'target': '/foreignkeytarget/1/'},
|
{'url': '/foreignkeysource/3/', 'name': 'source-3', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/foreignkeysource/4/', 'name': u'source-4', 'target': '/foreignkeytarget/2/'},
|
{'url': '/foreignkeysource/4/', 'name': 'source-4', 'target': '/foreignkeytarget/2/'},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_reverse_foreign_key_create(self):
|
def test_reverse_foreign_key_create(self):
|
||||||
data = {'url': '/foreignkeytarget/3/', 'name': u'target-3', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}
|
data = {'url': '/foreignkeytarget/3/', 'name': 'target-3', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']}
|
||||||
serializer = ForeignKeyTargetSerializer(data=data)
|
serializer = ForeignKeyTargetSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'target-3')
|
self.assertEqual(obj.name, 'target-3')
|
||||||
|
|
||||||
# Ensure target 4 is added, and everything else is as expected
|
# Ensure target 4 is added, and everything else is as expected
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
serializer = ForeignKeyTargetSerializer(queryset)
|
serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/foreignkeytarget/1/', 'name': u'target-1', 'sources': ['/foreignkeysource/2/']},
|
{'url': '/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['/foreignkeysource/2/']},
|
||||||
{'url': '/foreignkeytarget/2/', 'name': u'target-2', 'sources': []},
|
{'url': '/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
|
||||||
{'url': '/foreignkeytarget/3/', 'name': u'target-3', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']},
|
{'url': '/foreignkeytarget/3/', 'name': 'target-3', 'sources': ['/foreignkeysource/1/', '/foreignkeysource/3/']},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_update_with_invalid_null(self):
|
def test_foreign_key_update_with_invalid_null(self):
|
||||||
data = {'url': '/foreignkeysource/1/', 'name': u'source-1', 'target': None}
|
data = {'url': '/foreignkeysource/1/', 'name': 'source-1', 'target': None}
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
serializer = ForeignKeySourceSerializer(instance, data=data)
|
serializer = ForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEquals(serializer.errors, {'target': [u'Value may not be null']})
|
self.assertEquals(serializer.errors, {'target': ['Value may not be null']})
|
||||||
|
|
||||||
|
|
||||||
class HyperlinkedNullableForeignKeyTests(TestCase):
|
class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
|
@ -310,28 +312,28 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/nullableforeignkeysource/1/', 'name': u'source-1', 'target': '/foreignkeytarget/1/'},
|
{'url': '/nullableforeignkeysource/1/', 'name': 'source-1', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/nullableforeignkeysource/2/', 'name': u'source-2', 'target': '/foreignkeytarget/1/'},
|
{'url': '/nullableforeignkeysource/2/', 'name': 'source-2', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/nullableforeignkeysource/3/', 'name': u'source-3', 'target': None},
|
{'url': '/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_create_with_valid_null(self):
|
def test_foreign_key_create_with_valid_null(self):
|
||||||
data = {'url': '/nullableforeignkeysource/4/', 'name': u'source-4', 'target': None}
|
data = {'url': '/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
|
||||||
serializer = NullableForeignKeySourceSerializer(data=data)
|
serializer = NullableForeignKeySourceSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'source-4')
|
self.assertEqual(obj.name, 'source-4')
|
||||||
|
|
||||||
# Ensure source 4 is created, and everything else is as expected
|
# Ensure source 4 is created, and everything else is as expected
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/nullableforeignkeysource/1/', 'name': u'source-1', 'target': '/foreignkeytarget/1/'},
|
{'url': '/nullableforeignkeysource/1/', 'name': 'source-1', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/nullableforeignkeysource/2/', 'name': u'source-2', 'target': '/foreignkeytarget/1/'},
|
{'url': '/nullableforeignkeysource/2/', 'name': 'source-2', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/nullableforeignkeysource/3/', 'name': u'source-3', 'target': None},
|
{'url': '/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
|
||||||
{'url': '/nullableforeignkeysource/4/', 'name': u'source-4', 'target': None}
|
{'url': '/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -340,27 +342,27 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
The emptystring should be interpreted as null in the context
|
The emptystring should be interpreted as null in the context
|
||||||
of relationships.
|
of relationships.
|
||||||
"""
|
"""
|
||||||
data = {'url': '/nullableforeignkeysource/4/', 'name': u'source-4', 'target': ''}
|
data = {'url': '/nullableforeignkeysource/4/', 'name': 'source-4', 'target': ''}
|
||||||
expected_data = {'url': '/nullableforeignkeysource/4/', 'name': u'source-4', 'target': None}
|
expected_data = {'url': '/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
|
||||||
serializer = NullableForeignKeySourceSerializer(data=data)
|
serializer = NullableForeignKeySourceSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, expected_data)
|
self.assertEquals(serializer.data, expected_data)
|
||||||
self.assertEqual(obj.name, u'source-4')
|
self.assertEqual(obj.name, 'source-4')
|
||||||
|
|
||||||
# Ensure source 4 is created, and everything else is as expected
|
# Ensure source 4 is created, and everything else is as expected
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/nullableforeignkeysource/1/', 'name': u'source-1', 'target': '/foreignkeytarget/1/'},
|
{'url': '/nullableforeignkeysource/1/', 'name': 'source-1', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/nullableforeignkeysource/2/', 'name': u'source-2', 'target': '/foreignkeytarget/1/'},
|
{'url': '/nullableforeignkeysource/2/', 'name': 'source-2', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/nullableforeignkeysource/3/', 'name': u'source-3', 'target': None},
|
{'url': '/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
|
||||||
{'url': '/nullableforeignkeysource/4/', 'name': u'source-4', 'target': None}
|
{'url': '/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_update_with_valid_null(self):
|
def test_foreign_key_update_with_valid_null(self):
|
||||||
data = {'url': '/nullableforeignkeysource/1/', 'name': u'source-1', 'target': None}
|
data = {'url': '/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}
|
||||||
instance = NullableForeignKeySource.objects.get(pk=1)
|
instance = NullableForeignKeySource.objects.get(pk=1)
|
||||||
serializer = NullableForeignKeySourceSerializer(instance, data=data)
|
serializer = NullableForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -371,9 +373,9 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/nullableforeignkeysource/1/', 'name': u'source-1', 'target': None},
|
{'url': '/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None},
|
||||||
{'url': '/nullableforeignkeysource/2/', 'name': u'source-2', 'target': '/foreignkeytarget/1/'},
|
{'url': '/nullableforeignkeysource/2/', 'name': 'source-2', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/nullableforeignkeysource/3/', 'name': u'source-3', 'target': None},
|
{'url': '/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -382,8 +384,8 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
The emptystring should be interpreted as null in the context
|
The emptystring should be interpreted as null in the context
|
||||||
of relationships.
|
of relationships.
|
||||||
"""
|
"""
|
||||||
data = {'url': '/nullableforeignkeysource/1/', 'name': u'source-1', 'target': ''}
|
data = {'url': '/nullableforeignkeysource/1/', 'name': 'source-1', 'target': ''}
|
||||||
expected_data = {'url': '/nullableforeignkeysource/1/', 'name': u'source-1', 'target': None}
|
expected_data = {'url': '/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}
|
||||||
instance = NullableForeignKeySource.objects.get(pk=1)
|
instance = NullableForeignKeySource.objects.get(pk=1)
|
||||||
serializer = NullableForeignKeySourceSerializer(instance, data=data)
|
serializer = NullableForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -394,9 +396,9 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'url': '/nullableforeignkeysource/1/', 'name': u'source-1', 'target': None},
|
{'url': '/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None},
|
||||||
{'url': '/nullableforeignkeysource/2/', 'name': u'source-2', 'target': '/foreignkeytarget/1/'},
|
{'url': '/nullableforeignkeysource/2/', 'name': 'source-2', 'target': '/foreignkeytarget/1/'},
|
||||||
{'url': '/nullableforeignkeysource/3/', 'name': u'source-3', 'target': None},
|
{'url': '/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -405,7 +407,7 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
# and cannot be arbitrarily set.
|
# and cannot be arbitrarily set.
|
||||||
|
|
||||||
# def test_reverse_foreign_key_update(self):
|
# def test_reverse_foreign_key_update(self):
|
||||||
# data = {'id': 1, 'name': u'target-1', 'sources': [1]}
|
# data = {'id': 1, 'name': 'target-1', 'sources': [1]}
|
||||||
# instance = ForeignKeyTarget.objects.get(pk=1)
|
# instance = ForeignKeyTarget.objects.get(pk=1)
|
||||||
# serializer = ForeignKeyTargetSerializer(instance, data=data)
|
# serializer = ForeignKeyTargetSerializer(instance, data=data)
|
||||||
# self.assertTrue(serializer.is_valid())
|
# self.assertTrue(serializer.is_valid())
|
||||||
|
@ -416,8 +418,8 @@ class HyperlinkedNullableForeignKeyTests(TestCase):
|
||||||
# queryset = ForeignKeyTarget.objects.all()
|
# queryset = ForeignKeyTarget.objects.all()
|
||||||
# serializer = ForeignKeyTargetSerializer(queryset)
|
# serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
# expected = [
|
# expected = [
|
||||||
# {'id': 1, 'name': u'target-1', 'sources': [1]},
|
# {'id': 1, 'name': 'target-1', 'sources': [1]},
|
||||||
# {'id': 2, 'name': u'target-2', 'sources': []},
|
# {'id': 2, 'name': 'target-2', 'sources': []},
|
||||||
# ]
|
# ]
|
||||||
# self.assertEquals(serializer.data, expected)
|
# self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.tests.models import ForeignKeyTarget, ForeignKeySource, NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource
|
from rest_framework.tests.models import ForeignKeyTarget, ForeignKeySource, NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource
|
||||||
|
@ -53,9 +54,9 @@ class ReverseForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeySource.objects.all()
|
queryset = ForeignKeySource.objects.all()
|
||||||
serializer = ForeignKeySourceSerializer(queryset)
|
serializer = ForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': {'id': 1, 'name': u'target-1'}},
|
{'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
|
||||||
{'id': 2, 'name': u'source-2', 'target': {'id': 1, 'name': u'target-1'}},
|
{'id': 2, 'name': 'source-2', 'target': {'id': 1, 'name': 'target-1'}},
|
||||||
{'id': 3, 'name': u'source-3', 'target': {'id': 1, 'name': u'target-1'}},
|
{'id': 3, 'name': 'source-3', 'target': {'id': 1, 'name': 'target-1'}},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -63,12 +64,12 @@ class ReverseForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
serializer = ForeignKeyTargetSerializer(queryset)
|
serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'target-1', 'sources': [
|
{'id': 1, 'name': 'target-1', 'sources': [
|
||||||
{'id': 1, 'name': u'source-1', 'target': 1},
|
{'id': 1, 'name': 'source-1', 'target': 1},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': 1},
|
{'id': 3, 'name': 'source-3', 'target': 1},
|
||||||
]},
|
]},
|
||||||
{'id': 2, 'name': u'target-2', 'sources': [
|
{'id': 2, 'name': 'target-2', 'sources': [
|
||||||
]}
|
]}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
@ -88,9 +89,9 @@ class NestedNullableForeignKeyTests(TestCase):
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': {'id': 1, 'name': u'target-1'}},
|
{'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
|
||||||
{'id': 2, 'name': u'source-2', 'target': {'id': 1, 'name': u'target-1'}},
|
{'id': 2, 'name': 'source-2', 'target': {'id': 1, 'name': 'target-1'}},
|
||||||
{'id': 3, 'name': u'source-3', 'target': None},
|
{'id': 3, 'name': 'source-3', 'target': None},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import models
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
from rest_framework.tests.models import ManyToManyTarget, ManyToManySource, ForeignKeyTarget, ForeignKeySource, NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource
|
from rest_framework.tests.models import ManyToManyTarget, ManyToManySource, ForeignKeyTarget, ForeignKeySource, NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource
|
||||||
|
@ -56,9 +59,9 @@ class PKManyToManyTests(TestCase):
|
||||||
queryset = ManyToManySource.objects.all()
|
queryset = ManyToManySource.objects.all()
|
||||||
serializer = ManyToManySourceSerializer(queryset)
|
serializer = ManyToManySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'targets': [1]},
|
{'id': 1, 'name': 'source-1', 'targets': [1]},
|
||||||
{'id': 2, 'name': u'source-2', 'targets': [1, 2]},
|
{'id': 2, 'name': 'source-2', 'targets': [1, 2]},
|
||||||
{'id': 3, 'name': u'source-3', 'targets': [1, 2, 3]}
|
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -66,14 +69,14 @@ class PKManyToManyTests(TestCase):
|
||||||
queryset = ManyToManyTarget.objects.all()
|
queryset = ManyToManyTarget.objects.all()
|
||||||
serializer = ManyToManyTargetSerializer(queryset)
|
serializer = ManyToManyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'target-1', 'sources': [1, 2, 3]},
|
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
|
||||||
{'id': 2, 'name': u'target-2', 'sources': [2, 3]},
|
{'id': 2, 'name': 'target-2', 'sources': [2, 3]},
|
||||||
{'id': 3, 'name': u'target-3', 'sources': [3]}
|
{'id': 3, 'name': 'target-3', 'sources': [3]}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_many_to_many_update(self):
|
def test_many_to_many_update(self):
|
||||||
data = {'id': 1, 'name': u'source-1', 'targets': [1, 2, 3]}
|
data = {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]}
|
||||||
instance = ManyToManySource.objects.get(pk=1)
|
instance = ManyToManySource.objects.get(pk=1)
|
||||||
serializer = ManyToManySourceSerializer(instance, data=data)
|
serializer = ManyToManySourceSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -84,14 +87,14 @@ class PKManyToManyTests(TestCase):
|
||||||
queryset = ManyToManySource.objects.all()
|
queryset = ManyToManySource.objects.all()
|
||||||
serializer = ManyToManySourceSerializer(queryset)
|
serializer = ManyToManySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'targets': [1, 2, 3]},
|
{'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]},
|
||||||
{'id': 2, 'name': u'source-2', 'targets': [1, 2]},
|
{'id': 2, 'name': 'source-2', 'targets': [1, 2]},
|
||||||
{'id': 3, 'name': u'source-3', 'targets': [1, 2, 3]}
|
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_reverse_many_to_many_update(self):
|
def test_reverse_many_to_many_update(self):
|
||||||
data = {'id': 1, 'name': u'target-1', 'sources': [1]}
|
data = {'id': 1, 'name': 'target-1', 'sources': [1]}
|
||||||
instance = ManyToManyTarget.objects.get(pk=1)
|
instance = ManyToManyTarget.objects.get(pk=1)
|
||||||
serializer = ManyToManyTargetSerializer(instance, data=data)
|
serializer = ManyToManyTargetSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -102,47 +105,47 @@ class PKManyToManyTests(TestCase):
|
||||||
queryset = ManyToManyTarget.objects.all()
|
queryset = ManyToManyTarget.objects.all()
|
||||||
serializer = ManyToManyTargetSerializer(queryset)
|
serializer = ManyToManyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'target-1', 'sources': [1]},
|
{'id': 1, 'name': 'target-1', 'sources': [1]},
|
||||||
{'id': 2, 'name': u'target-2', 'sources': [2, 3]},
|
{'id': 2, 'name': 'target-2', 'sources': [2, 3]},
|
||||||
{'id': 3, 'name': u'target-3', 'sources': [3]}
|
{'id': 3, 'name': 'target-3', 'sources': [3]}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_many_to_many_create(self):
|
def test_many_to_many_create(self):
|
||||||
data = {'id': 4, 'name': u'source-4', 'targets': [1, 3]}
|
data = {'id': 4, 'name': 'source-4', 'targets': [1, 3]}
|
||||||
serializer = ManyToManySourceSerializer(data=data)
|
serializer = ManyToManySourceSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'source-4')
|
self.assertEqual(obj.name, 'source-4')
|
||||||
|
|
||||||
# Ensure source 4 is added, and everything else is as expected
|
# Ensure source 4 is added, and everything else is as expected
|
||||||
queryset = ManyToManySource.objects.all()
|
queryset = ManyToManySource.objects.all()
|
||||||
serializer = ManyToManySourceSerializer(queryset)
|
serializer = ManyToManySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'targets': [1]},
|
{'id': 1, 'name': 'source-1', 'targets': [1]},
|
||||||
{'id': 2, 'name': u'source-2', 'targets': [1, 2]},
|
{'id': 2, 'name': 'source-2', 'targets': [1, 2]},
|
||||||
{'id': 3, 'name': u'source-3', 'targets': [1, 2, 3]},
|
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]},
|
||||||
{'id': 4, 'name': u'source-4', 'targets': [1, 3]},
|
{'id': 4, 'name': 'source-4', 'targets': [1, 3]},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_reverse_many_to_many_create(self):
|
def test_reverse_many_to_many_create(self):
|
||||||
data = {'id': 4, 'name': u'target-4', 'sources': [1, 3]}
|
data = {'id': 4, 'name': 'target-4', 'sources': [1, 3]}
|
||||||
serializer = ManyToManyTargetSerializer(data=data)
|
serializer = ManyToManyTargetSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'target-4')
|
self.assertEqual(obj.name, 'target-4')
|
||||||
|
|
||||||
# Ensure target 4 is added, and everything else is as expected
|
# Ensure target 4 is added, and everything else is as expected
|
||||||
queryset = ManyToManyTarget.objects.all()
|
queryset = ManyToManyTarget.objects.all()
|
||||||
serializer = ManyToManyTargetSerializer(queryset)
|
serializer = ManyToManyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'target-1', 'sources': [1, 2, 3]},
|
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
|
||||||
{'id': 2, 'name': u'target-2', 'sources': [2, 3]},
|
{'id': 2, 'name': 'target-2', 'sources': [2, 3]},
|
||||||
{'id': 3, 'name': u'target-3', 'sources': [3]},
|
{'id': 3, 'name': 'target-3', 'sources': [3]},
|
||||||
{'id': 4, 'name': u'target-4', 'sources': [1, 3]}
|
{'id': 4, 'name': 'target-4', 'sources': [1, 3]}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -161,9 +164,9 @@ class PKForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeySource.objects.all()
|
queryset = ForeignKeySource.objects.all()
|
||||||
serializer = ForeignKeySourceSerializer(queryset)
|
serializer = ForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': 1},
|
{'id': 1, 'name': 'source-1', 'target': 1},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': 1}
|
{'id': 3, 'name': 'source-3', 'target': 1}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -171,13 +174,13 @@ class PKForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
serializer = ForeignKeyTargetSerializer(queryset)
|
serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'target-1', 'sources': [1, 2, 3]},
|
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
|
||||||
{'id': 2, 'name': u'target-2', 'sources': []},
|
{'id': 2, 'name': 'target-2', 'sources': []},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_update(self):
|
def test_foreign_key_update(self):
|
||||||
data = {'id': 1, 'name': u'source-1', 'target': 2}
|
data = {'id': 1, 'name': 'source-1', 'target': 2}
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
serializer = ForeignKeySourceSerializer(instance, data=data)
|
serializer = ForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -188,9 +191,9 @@ class PKForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeySource.objects.all()
|
queryset = ForeignKeySource.objects.all()
|
||||||
serializer = ForeignKeySourceSerializer(queryset)
|
serializer = ForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': 2},
|
{'id': 1, 'name': 'source-1', 'target': 2},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': 1}
|
{'id': 3, 'name': 'source-3', 'target': 1}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -202,7 +205,7 @@ class PKForeignKeyTests(TestCase):
|
||||||
self.assertEquals(serializer.errors, {'target': [u'Incorrect type. Expected pk value, received str.']})
|
self.assertEquals(serializer.errors, {'target': [u'Incorrect type. Expected pk value, received str.']})
|
||||||
|
|
||||||
def test_reverse_foreign_key_update(self):
|
def test_reverse_foreign_key_update(self):
|
||||||
data = {'id': 2, 'name': u'target-2', 'sources': [1, 3]}
|
data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]}
|
||||||
instance = ForeignKeyTarget.objects.get(pk=2)
|
instance = ForeignKeyTarget.objects.get(pk=2)
|
||||||
serializer = ForeignKeyTargetSerializer(instance, data=data)
|
serializer = ForeignKeyTargetSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -211,8 +214,8 @@ class PKForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
new_serializer = ForeignKeyTargetSerializer(queryset)
|
new_serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'target-1', 'sources': [1, 2, 3]},
|
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
|
||||||
{'id': 2, 'name': u'target-2', 'sources': []},
|
{'id': 2, 'name': 'target-2', 'sources': []},
|
||||||
]
|
]
|
||||||
self.assertEquals(new_serializer.data, expected)
|
self.assertEquals(new_serializer.data, expected)
|
||||||
|
|
||||||
|
@ -223,54 +226,54 @@ class PKForeignKeyTests(TestCase):
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
serializer = ForeignKeyTargetSerializer(queryset)
|
serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'target-1', 'sources': [2]},
|
{'id': 1, 'name': 'target-1', 'sources': [2]},
|
||||||
{'id': 2, 'name': u'target-2', 'sources': [1, 3]},
|
{'id': 2, 'name': 'target-2', 'sources': [1, 3]},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_create(self):
|
def test_foreign_key_create(self):
|
||||||
data = {'id': 4, 'name': u'source-4', 'target': 2}
|
data = {'id': 4, 'name': 'source-4', 'target': 2}
|
||||||
serializer = ForeignKeySourceSerializer(data=data)
|
serializer = ForeignKeySourceSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'source-4')
|
self.assertEqual(obj.name, 'source-4')
|
||||||
|
|
||||||
# Ensure source 4 is added, and everything else is as expected
|
# Ensure source 4 is added, and everything else is as expected
|
||||||
queryset = ForeignKeySource.objects.all()
|
queryset = ForeignKeySource.objects.all()
|
||||||
serializer = ForeignKeySourceSerializer(queryset)
|
serializer = ForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': 1},
|
{'id': 1, 'name': 'source-1', 'target': 1},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': 1},
|
{'id': 3, 'name': 'source-3', 'target': 1},
|
||||||
{'id': 4, 'name': u'source-4', 'target': 2},
|
{'id': 4, 'name': 'source-4', 'target': 2},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_reverse_foreign_key_create(self):
|
def test_reverse_foreign_key_create(self):
|
||||||
data = {'id': 3, 'name': u'target-3', 'sources': [1, 3]}
|
data = {'id': 3, 'name': 'target-3', 'sources': [1, 3]}
|
||||||
serializer = ForeignKeyTargetSerializer(data=data)
|
serializer = ForeignKeyTargetSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'target-3')
|
self.assertEqual(obj.name, 'target-3')
|
||||||
|
|
||||||
# Ensure target 3 is added, and everything else is as expected
|
# Ensure target 3 is added, and everything else is as expected
|
||||||
queryset = ForeignKeyTarget.objects.all()
|
queryset = ForeignKeyTarget.objects.all()
|
||||||
serializer = ForeignKeyTargetSerializer(queryset)
|
serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'target-1', 'sources': [2]},
|
{'id': 1, 'name': 'target-1', 'sources': [2]},
|
||||||
{'id': 2, 'name': u'target-2', 'sources': []},
|
{'id': 2, 'name': 'target-2', 'sources': []},
|
||||||
{'id': 3, 'name': u'target-3', 'sources': [1, 3]},
|
{'id': 3, 'name': 'target-3', 'sources': [1, 3]},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_update_with_invalid_null(self):
|
def test_foreign_key_update_with_invalid_null(self):
|
||||||
data = {'id': 1, 'name': u'source-1', 'target': None}
|
data = {'id': 1, 'name': 'source-1', 'target': None}
|
||||||
instance = ForeignKeySource.objects.get(pk=1)
|
instance = ForeignKeySource.objects.get(pk=1)
|
||||||
serializer = ForeignKeySourceSerializer(instance, data=data)
|
serializer = ForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEquals(serializer.errors, {'target': [u'Value may not be null']})
|
self.assertEquals(serializer.errors, {'target': ['Value may not be null']})
|
||||||
|
|
||||||
|
|
||||||
class PKNullableForeignKeyTests(TestCase):
|
class PKNullableForeignKeyTests(TestCase):
|
||||||
|
@ -287,28 +290,28 @@ class PKNullableForeignKeyTests(TestCase):
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': 1},
|
{'id': 1, 'name': 'source-1', 'target': 1},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': None},
|
{'id': 3, 'name': 'source-3', 'target': None},
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_create_with_valid_null(self):
|
def test_foreign_key_create_with_valid_null(self):
|
||||||
data = {'id': 4, 'name': u'source-4', 'target': None}
|
data = {'id': 4, 'name': 'source-4', 'target': None}
|
||||||
serializer = NullableForeignKeySourceSerializer(data=data)
|
serializer = NullableForeignKeySourceSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, data)
|
self.assertEquals(serializer.data, data)
|
||||||
self.assertEqual(obj.name, u'source-4')
|
self.assertEqual(obj.name, 'source-4')
|
||||||
|
|
||||||
# Ensure source 4 is created, and everything else is as expected
|
# Ensure source 4 is created, and everything else is as expected
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': 1},
|
{'id': 1, 'name': 'source-1', 'target': 1},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': None},
|
{'id': 3, 'name': 'source-3', 'target': None},
|
||||||
{'id': 4, 'name': u'source-4', 'target': None}
|
{'id': 4, 'name': 'source-4', 'target': None}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -317,27 +320,27 @@ class PKNullableForeignKeyTests(TestCase):
|
||||||
The emptystring should be interpreted as null in the context
|
The emptystring should be interpreted as null in the context
|
||||||
of relationships.
|
of relationships.
|
||||||
"""
|
"""
|
||||||
data = {'id': 4, 'name': u'source-4', 'target': ''}
|
data = {'id': 4, 'name': 'source-4', 'target': ''}
|
||||||
expected_data = {'id': 4, 'name': u'source-4', 'target': None}
|
expected_data = {'id': 4, 'name': 'source-4', 'target': None}
|
||||||
serializer = NullableForeignKeySourceSerializer(data=data)
|
serializer = NullableForeignKeySourceSerializer(data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
obj = serializer.save()
|
obj = serializer.save()
|
||||||
self.assertEquals(serializer.data, expected_data)
|
self.assertEquals(serializer.data, expected_data)
|
||||||
self.assertEqual(obj.name, u'source-4')
|
self.assertEqual(obj.name, 'source-4')
|
||||||
|
|
||||||
# Ensure source 4 is created, and everything else is as expected
|
# Ensure source 4 is created, and everything else is as expected
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': 1},
|
{'id': 1, 'name': 'source-1', 'target': 1},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': None},
|
{'id': 3, 'name': 'source-3', 'target': None},
|
||||||
{'id': 4, 'name': u'source-4', 'target': None}
|
{'id': 4, 'name': 'source-4', 'target': None}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
def test_foreign_key_update_with_valid_null(self):
|
def test_foreign_key_update_with_valid_null(self):
|
||||||
data = {'id': 1, 'name': u'source-1', 'target': None}
|
data = {'id': 1, 'name': 'source-1', 'target': None}
|
||||||
instance = NullableForeignKeySource.objects.get(pk=1)
|
instance = NullableForeignKeySource.objects.get(pk=1)
|
||||||
serializer = NullableForeignKeySourceSerializer(instance, data=data)
|
serializer = NullableForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -348,9 +351,9 @@ class PKNullableForeignKeyTests(TestCase):
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': None},
|
{'id': 1, 'name': 'source-1', 'target': None},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': None}
|
{'id': 3, 'name': 'source-3', 'target': None}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -359,8 +362,8 @@ class PKNullableForeignKeyTests(TestCase):
|
||||||
The emptystring should be interpreted as null in the context
|
The emptystring should be interpreted as null in the context
|
||||||
of relationships.
|
of relationships.
|
||||||
"""
|
"""
|
||||||
data = {'id': 1, 'name': u'source-1', 'target': ''}
|
data = {'id': 1, 'name': 'source-1', 'target': ''}
|
||||||
expected_data = {'id': 1, 'name': u'source-1', 'target': None}
|
expected_data = {'id': 1, 'name': 'source-1', 'target': None}
|
||||||
instance = NullableForeignKeySource.objects.get(pk=1)
|
instance = NullableForeignKeySource.objects.get(pk=1)
|
||||||
serializer = NullableForeignKeySourceSerializer(instance, data=data)
|
serializer = NullableForeignKeySourceSerializer(instance, data=data)
|
||||||
self.assertTrue(serializer.is_valid())
|
self.assertTrue(serializer.is_valid())
|
||||||
|
@ -371,9 +374,9 @@ class PKNullableForeignKeyTests(TestCase):
|
||||||
queryset = NullableForeignKeySource.objects.all()
|
queryset = NullableForeignKeySource.objects.all()
|
||||||
serializer = NullableForeignKeySourceSerializer(queryset)
|
serializer = NullableForeignKeySourceSerializer(queryset)
|
||||||
expected = [
|
expected = [
|
||||||
{'id': 1, 'name': u'source-1', 'target': None},
|
{'id': 1, 'name': 'source-1', 'target': None},
|
||||||
{'id': 2, 'name': u'source-2', 'target': 1},
|
{'id': 2, 'name': 'source-2', 'target': 1},
|
||||||
{'id': 3, 'name': u'source-3', 'target': None}
|
{'id': 3, 'name': 'source-3', 'target': None}
|
||||||
]
|
]
|
||||||
self.assertEquals(serializer.data, expected)
|
self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -382,7 +385,7 @@ class PKNullableForeignKeyTests(TestCase):
|
||||||
# and cannot be arbitrarily set.
|
# and cannot be arbitrarily set.
|
||||||
|
|
||||||
# def test_reverse_foreign_key_update(self):
|
# def test_reverse_foreign_key_update(self):
|
||||||
# data = {'id': 1, 'name': u'target-1', 'sources': [1]}
|
# data = {'id': 1, 'name': 'target-1', 'sources': [1]}
|
||||||
# instance = ForeignKeyTarget.objects.get(pk=1)
|
# instance = ForeignKeyTarget.objects.get(pk=1)
|
||||||
# serializer = ForeignKeyTargetSerializer(instance, data=data)
|
# serializer = ForeignKeyTargetSerializer(instance, data=data)
|
||||||
# self.assertTrue(serializer.is_valid())
|
# self.assertTrue(serializer.is_valid())
|
||||||
|
@ -393,8 +396,8 @@ class PKNullableForeignKeyTests(TestCase):
|
||||||
# queryset = ForeignKeyTarget.objects.all()
|
# queryset = ForeignKeyTarget.objects.all()
|
||||||
# serializer = ForeignKeyTargetSerializer(queryset)
|
# serializer = ForeignKeyTargetSerializer(queryset)
|
||||||
# expected = [
|
# expected = [
|
||||||
# {'id': 1, 'name': u'target-1', 'sources': [1]},
|
# {'id': 1, 'name': 'target-1', 'sources': [1]},
|
||||||
# {'id': 2, 'name': u'target-2', 'sources': []},
|
# {'id': 2, 'name': 'target-2', 'sources': []},
|
||||||
# ]
|
# ]
|
||||||
# self.assertEquals(serializer.data, expected)
|
# self.assertEquals(serializer.data, expected)
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,8 @@ from rest_framework.renderers import BaseRenderer, JSONRenderer, YAMLRenderer, \
|
||||||
from rest_framework.parsers import YAMLParser, XMLParser
|
from rest_framework.parsers import YAMLParser, XMLParser
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
|
|
||||||
from StringIO import StringIO
|
from rest_framework.compat import StringIO
|
||||||
|
from rest_framework.compat import six
|
||||||
import datetime
|
import datetime
|
||||||
from decimal import Decimal
|
from decimal import Decimal
|
||||||
|
|
||||||
|
@ -22,8 +23,8 @@ from decimal import Decimal
|
||||||
DUMMYSTATUS = status.HTTP_200_OK
|
DUMMYSTATUS = status.HTTP_200_OK
|
||||||
DUMMYCONTENT = 'dummycontent'
|
DUMMYCONTENT = 'dummycontent'
|
||||||
|
|
||||||
RENDERER_A_SERIALIZER = lambda x: 'Renderer A: %s' % x
|
RENDERER_A_SERIALIZER = lambda x: ('Renderer A: %s' % x).encode('ascii')
|
||||||
RENDERER_B_SERIALIZER = lambda x: 'Renderer B: %s' % x
|
RENDERER_B_SERIALIZER = lambda x: ('Renderer B: %s' % x).encode('ascii')
|
||||||
|
|
||||||
|
|
||||||
expected_results = [
|
expected_results = [
|
||||||
|
@ -140,7 +141,7 @@ class RendererEndToEndTests(TestCase):
|
||||||
resp = self.client.head('/')
|
resp = self.client.head('/')
|
||||||
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
||||||
self.assertEquals(resp['Content-Type'], RendererA.media_type)
|
self.assertEquals(resp['Content-Type'], RendererA.media_type)
|
||||||
self.assertEquals(resp.content, '')
|
self.assertEquals(resp.content, six.b(''))
|
||||||
|
|
||||||
def test_default_renderer_serializes_content_on_accept_any(self):
|
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."""
|
||||||
|
@ -267,7 +268,8 @@ class JSONPRendererTests(TestCase):
|
||||||
HTTP_ACCEPT='application/javascript')
|
HTTP_ACCEPT='application/javascript')
|
||||||
self.assertEquals(resp.status_code, 200)
|
self.assertEquals(resp.status_code, 200)
|
||||||
self.assertEquals(resp['Content-Type'], 'application/javascript')
|
self.assertEquals(resp['Content-Type'], 'application/javascript')
|
||||||
self.assertEquals(resp.content, 'callback(%s);' % _flat_repr)
|
self.assertEquals(resp.content,
|
||||||
|
('callback(%s);' % _flat_repr).encode('ascii'))
|
||||||
|
|
||||||
def test_without_callback_without_json_renderer(self):
|
def test_without_callback_without_json_renderer(self):
|
||||||
"""
|
"""
|
||||||
|
@ -277,7 +279,8 @@ class JSONPRendererTests(TestCase):
|
||||||
HTTP_ACCEPT='application/javascript')
|
HTTP_ACCEPT='application/javascript')
|
||||||
self.assertEquals(resp.status_code, 200)
|
self.assertEquals(resp.status_code, 200)
|
||||||
self.assertEquals(resp['Content-Type'], 'application/javascript')
|
self.assertEquals(resp['Content-Type'], 'application/javascript')
|
||||||
self.assertEquals(resp.content, 'callback(%s);' % _flat_repr)
|
self.assertEquals(resp.content,
|
||||||
|
('callback(%s);' % _flat_repr).encode('ascii'))
|
||||||
|
|
||||||
def test_with_callback(self):
|
def test_with_callback(self):
|
||||||
"""
|
"""
|
||||||
|
@ -288,7 +291,8 @@ class JSONPRendererTests(TestCase):
|
||||||
HTTP_ACCEPT='application/javascript')
|
HTTP_ACCEPT='application/javascript')
|
||||||
self.assertEquals(resp.status_code, 200)
|
self.assertEquals(resp.status_code, 200)
|
||||||
self.assertEquals(resp['Content-Type'], 'application/javascript')
|
self.assertEquals(resp['Content-Type'], 'application/javascript')
|
||||||
self.assertEquals(resp.content, '%s(%s);' % (callback_func, _flat_repr))
|
self.assertEquals(resp.content,
|
||||||
|
('%s(%s);' % (callback_func, _flat_repr)).encode('ascii'))
|
||||||
|
|
||||||
|
|
||||||
if yaml:
|
if yaml:
|
||||||
|
|
|
@ -20,6 +20,7 @@ from rest_framework.request import Request
|
||||||
from rest_framework.response import Response
|
from rest_framework.response import Response
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
from rest_framework.views import APIView
|
from rest_framework.views import APIView
|
||||||
|
from rest_framework.compat import six
|
||||||
|
|
||||||
|
|
||||||
factory = RequestFactory()
|
factory = RequestFactory()
|
||||||
|
@ -79,14 +80,14 @@ class TestContentParsing(TestCase):
|
||||||
data = {'qwerty': 'uiop'}
|
data = {'qwerty': 'uiop'}
|
||||||
request = Request(factory.post('/', data))
|
request = Request(factory.post('/', data))
|
||||||
request.parsers = (FormParser(), MultiPartParser())
|
request.parsers = (FormParser(), MultiPartParser())
|
||||||
self.assertEqual(request.DATA.items(), data.items())
|
self.assertEqual(list(request.DATA.items()), list(data.items()))
|
||||||
|
|
||||||
def test_request_DATA_with_text_content(self):
|
def test_request_DATA_with_text_content(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns content for POST request with
|
Ensure request.DATA returns content for POST request with
|
||||||
non-form content.
|
non-form content.
|
||||||
"""
|
"""
|
||||||
content = 'qwerty'
|
content = six.b('qwerty')
|
||||||
content_type = 'text/plain'
|
content_type = 'text/plain'
|
||||||
request = Request(factory.post('/', content, content_type=content_type))
|
request = Request(factory.post('/', content, content_type=content_type))
|
||||||
request.parsers = (PlainTextParser(),)
|
request.parsers = (PlainTextParser(),)
|
||||||
|
@ -99,7 +100,7 @@ class TestContentParsing(TestCase):
|
||||||
data = {'qwerty': 'uiop'}
|
data = {'qwerty': 'uiop'}
|
||||||
request = Request(factory.post('/', data))
|
request = Request(factory.post('/', data))
|
||||||
request.parsers = (FormParser(), MultiPartParser())
|
request.parsers = (FormParser(), MultiPartParser())
|
||||||
self.assertEqual(request.POST.items(), data.items())
|
self.assertEqual(list(request.POST.items()), list(data.items()))
|
||||||
|
|
||||||
def test_standard_behaviour_determines_form_content_PUT(self):
|
def test_standard_behaviour_determines_form_content_PUT(self):
|
||||||
"""
|
"""
|
||||||
|
@ -117,14 +118,14 @@ class TestContentParsing(TestCase):
|
||||||
request = Request(factory.put('/', data))
|
request = Request(factory.put('/', data))
|
||||||
|
|
||||||
request.parsers = (FormParser(), MultiPartParser())
|
request.parsers = (FormParser(), MultiPartParser())
|
||||||
self.assertEqual(request.DATA.items(), data.items())
|
self.assertEqual(list(request.DATA.items()), list(data.items()))
|
||||||
|
|
||||||
def test_standard_behaviour_determines_non_form_content_PUT(self):
|
def test_standard_behaviour_determines_non_form_content_PUT(self):
|
||||||
"""
|
"""
|
||||||
Ensure request.DATA returns content for PUT request with
|
Ensure request.DATA returns content for PUT request with
|
||||||
non-form content.
|
non-form content.
|
||||||
"""
|
"""
|
||||||
content = 'qwerty'
|
content = six.b('qwerty')
|
||||||
content_type = 'text/plain'
|
content_type = 'text/plain'
|
||||||
request = Request(factory.put('/', content, content_type=content_type))
|
request = Request(factory.put('/', content, content_type=content_type))
|
||||||
request.parsers = (PlainTextParser(), )
|
request.parsers = (PlainTextParser(), )
|
||||||
|
|
|
@ -9,6 +9,7 @@ from rest_framework.renderers import (
|
||||||
BrowsableAPIRenderer
|
BrowsableAPIRenderer
|
||||||
)
|
)
|
||||||
from rest_framework.settings import api_settings
|
from rest_framework.settings import api_settings
|
||||||
|
from rest_framework.compat import six
|
||||||
|
|
||||||
|
|
||||||
class MockPickleRenderer(BaseRenderer):
|
class MockPickleRenderer(BaseRenderer):
|
||||||
|
@ -22,8 +23,8 @@ class MockJsonRenderer(BaseRenderer):
|
||||||
DUMMYSTATUS = status.HTTP_200_OK
|
DUMMYSTATUS = status.HTTP_200_OK
|
||||||
DUMMYCONTENT = 'dummycontent'
|
DUMMYCONTENT = 'dummycontent'
|
||||||
|
|
||||||
RENDERER_A_SERIALIZER = lambda x: 'Renderer A: %s' % x
|
RENDERER_A_SERIALIZER = lambda x: ('Renderer A: %s' % x).encode('ascii')
|
||||||
RENDERER_B_SERIALIZER = lambda x: 'Renderer B: %s' % x
|
RENDERER_B_SERIALIZER = lambda x: ('Renderer B: %s' % x).encode('ascii')
|
||||||
|
|
||||||
|
|
||||||
class RendererA(BaseRenderer):
|
class RendererA(BaseRenderer):
|
||||||
|
@ -92,7 +93,7 @@ class RendererIntegrationTests(TestCase):
|
||||||
resp = self.client.head('/')
|
resp = self.client.head('/')
|
||||||
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
self.assertEquals(resp.status_code, DUMMYSTATUS)
|
||||||
self.assertEquals(resp['Content-Type'], RendererA.media_type)
|
self.assertEquals(resp['Content-Type'], RendererA.media_type)
|
||||||
self.assertEquals(resp.content, '')
|
self.assertEquals(resp.content, six.b(''))
|
||||||
|
|
||||||
def test_default_renderer_serializes_content_on_accept_any(self):
|
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."""
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import datetime
|
import datetime
|
||||||
import pickle
|
import pickle
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
|
@ -200,12 +202,12 @@ class ValidationTests(TestCase):
|
||||||
def test_create(self):
|
def test_create(self):
|
||||||
serializer = CommentSerializer(data=self.data)
|
serializer = CommentSerializer(data=self.data)
|
||||||
self.assertEquals(serializer.is_valid(), False)
|
self.assertEquals(serializer.is_valid(), False)
|
||||||
self.assertEquals(serializer.errors, {'content': [u'Ensure this value has at most 1000 characters (it has 1001).']})
|
self.assertEquals(serializer.errors, {'content': ['Ensure this value has at most 1000 characters (it has 1001).']})
|
||||||
|
|
||||||
def test_update(self):
|
def test_update(self):
|
||||||
serializer = CommentSerializer(self.comment, data=self.data)
|
serializer = CommentSerializer(self.comment, data=self.data)
|
||||||
self.assertEquals(serializer.is_valid(), False)
|
self.assertEquals(serializer.is_valid(), False)
|
||||||
self.assertEquals(serializer.errors, {'content': [u'Ensure this value has at most 1000 characters (it has 1001).']})
|
self.assertEquals(serializer.errors, {'content': ['Ensure this value has at most 1000 characters (it has 1001).']})
|
||||||
|
|
||||||
def test_update_missing_field(self):
|
def test_update_missing_field(self):
|
||||||
data = {
|
data = {
|
||||||
|
@ -214,7 +216,7 @@ class ValidationTests(TestCase):
|
||||||
}
|
}
|
||||||
serializer = CommentSerializer(self.comment, data=data)
|
serializer = CommentSerializer(self.comment, data=data)
|
||||||
self.assertEquals(serializer.is_valid(), False)
|
self.assertEquals(serializer.is_valid(), False)
|
||||||
self.assertEquals(serializer.errors, {'email': [u'This field is required.']})
|
self.assertEquals(serializer.errors, {'email': ['This field is required.']})
|
||||||
|
|
||||||
def test_missing_bool_with_default(self):
|
def test_missing_bool_with_default(self):
|
||||||
"""Make sure that a boolean value with a 'False' value is not
|
"""Make sure that a boolean value with a 'False' value is not
|
||||||
|
@ -268,7 +270,7 @@ class ValidationTests(TestCase):
|
||||||
|
|
||||||
serializer = CommentSerializerWithCrossFieldValidator(data=data)
|
serializer = CommentSerializerWithCrossFieldValidator(data=data)
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEquals(serializer.errors, {'non_field_errors': [u'Email address not in content']})
|
self.assertEquals(serializer.errors, {'non_field_errors': ['Email address not in content']})
|
||||||
|
|
||||||
def test_null_is_true_fields(self):
|
def test_null_is_true_fields(self):
|
||||||
"""
|
"""
|
||||||
|
@ -284,7 +286,7 @@ class ValidationTests(TestCase):
|
||||||
}
|
}
|
||||||
serializer = ActionItemSerializer(data=data)
|
serializer = ActionItemSerializer(data=data)
|
||||||
self.assertEquals(serializer.is_valid(), False)
|
self.assertEquals(serializer.is_valid(), False)
|
||||||
self.assertEquals(serializer.errors, {'title': [u'Ensure this value has at most 200 characters (it has 201).']})
|
self.assertEquals(serializer.errors, {'title': ['Ensure this value has at most 200 characters (it has 201).']})
|
||||||
|
|
||||||
def test_modelserializer_max_length_exceeded_with_custom_restore(self):
|
def test_modelserializer_max_length_exceeded_with_custom_restore(self):
|
||||||
"""
|
"""
|
||||||
|
@ -307,7 +309,7 @@ class ValidationTests(TestCase):
|
||||||
}
|
}
|
||||||
serializer = ActionItemSerializer(data=data)
|
serializer = ActionItemSerializer(data=data)
|
||||||
self.assertEquals(serializer.is_valid(), False)
|
self.assertEquals(serializer.is_valid(), False)
|
||||||
self.assertEquals(serializer.errors, {'info': [u'Ensure this value has at most 12 characters (it has 13).']})
|
self.assertEquals(serializer.errors, {'info': ['Ensure this value has at most 12 characters (it has 13).']})
|
||||||
|
|
||||||
|
|
||||||
class CustomValidationTests(TestCase):
|
class CustomValidationTests(TestCase):
|
||||||
|
@ -383,7 +385,7 @@ class ModelValidationTests(TestCase):
|
||||||
serializer.save()
|
serializer.save()
|
||||||
second_serializer = AlbumsSerializer(data={'title': 'a'})
|
second_serializer = AlbumsSerializer(data={'title': 'a'})
|
||||||
self.assertFalse(second_serializer.is_valid())
|
self.assertFalse(second_serializer.is_valid())
|
||||||
self.assertEqual(second_serializer.errors, {'title': [u'Album with this Title already exists.']})
|
self.assertEqual(second_serializer.errors, {'title': ['Album with this Title already exists.']})
|
||||||
|
|
||||||
def test_foreign_key_with_partial(self):
|
def test_foreign_key_with_partial(self):
|
||||||
"""
|
"""
|
||||||
|
@ -421,15 +423,15 @@ class RegexValidationTest(TestCase):
|
||||||
def test_create_failed(self):
|
def test_create_failed(self):
|
||||||
serializer = BookSerializer(data={'isbn': '1234567890'})
|
serializer = BookSerializer(data={'isbn': '1234567890'})
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']})
|
self.assertEquals(serializer.errors, {'isbn': ['isbn has to be exact 13 numbers']})
|
||||||
|
|
||||||
serializer = BookSerializer(data={'isbn': '12345678901234'})
|
serializer = BookSerializer(data={'isbn': '12345678901234'})
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']})
|
self.assertEquals(serializer.errors, {'isbn': ['isbn has to be exact 13 numbers']})
|
||||||
|
|
||||||
serializer = BookSerializer(data={'isbn': 'abcdefghijklm'})
|
serializer = BookSerializer(data={'isbn': 'abcdefghijklm'})
|
||||||
self.assertFalse(serializer.is_valid())
|
self.assertFalse(serializer.is_valid())
|
||||||
self.assertEquals(serializer.errors, {'isbn': [u'isbn has to be exact 13 numbers']})
|
self.assertEquals(serializer.errors, {'isbn': ['isbn has to be exact 13 numbers']})
|
||||||
|
|
||||||
def test_create_success(self):
|
def test_create_success(self):
|
||||||
serializer = BookSerializer(data={'isbn': '1234567890123'})
|
serializer = BookSerializer(data={'isbn': '1234567890123'})
|
||||||
|
@ -743,11 +745,11 @@ class RelatedTraversalTest(TestCase):
|
||||||
serializer = BlogPostSerializer(instance=post)
|
serializer = BlogPostSerializer(instance=post)
|
||||||
|
|
||||||
expected = {
|
expected = {
|
||||||
'title': u'Test blog post',
|
'title': 'Test blog post',
|
||||||
'comments': [{
|
'comments': [{
|
||||||
'text': u'I love this blog post',
|
'text': 'I love this blog post',
|
||||||
'post_owner': {
|
'post_owner': {
|
||||||
"name": u"django",
|
"name": "django",
|
||||||
"age": None
|
"age": None
|
||||||
}
|
}
|
||||||
}]
|
}]
|
||||||
|
@ -782,8 +784,8 @@ class SerializerMethodFieldTests(TestCase):
|
||||||
serializer = self.serializer_class(source_data)
|
serializer = self.serializer_class(source_data)
|
||||||
|
|
||||||
expected = {
|
expected = {
|
||||||
'beep': u'hello!',
|
'beep': 'hello!',
|
||||||
'boop': [u'a', u'b', u'c'],
|
'boop': ['a', 'b', 'c'],
|
||||||
'boop_count': 3,
|
'boop_count': 3,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -882,8 +884,8 @@ class DepthTest(TestCase):
|
||||||
depth = 1
|
depth = 1
|
||||||
|
|
||||||
serializer = BlogPostSerializer(instance=post)
|
serializer = BlogPostSerializer(instance=post)
|
||||||
expected = {'id': 1, 'title': u'Test blog post',
|
expected = {'id': 1, 'title': 'Test blog post',
|
||||||
'writer': {'id': 1, 'name': u'django', 'age': 1}}
|
'writer': {'id': 1, 'name': 'django', 'age': 1}}
|
||||||
|
|
||||||
self.assertEqual(serializer.data, expected)
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
@ -902,8 +904,8 @@ class DepthTest(TestCase):
|
||||||
model = BlogPost
|
model = BlogPost
|
||||||
|
|
||||||
serializer = BlogPostSerializer(instance=post)
|
serializer = BlogPostSerializer(instance=post)
|
||||||
expected = {'id': 1, 'title': u'Test blog post',
|
expected = {'id': 1, 'title': 'Test blog post',
|
||||||
'writer': {'id': 1, 'name': u'django', 'age': 1}}
|
'writer': {'id': 1, 'name': 'django', 'age': 1}}
|
||||||
|
|
||||||
self.assertEqual(serializer.data, expected)
|
self.assertEqual(serializer.data, expected)
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,5 @@
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
import copy
|
import copy
|
||||||
from django.test import TestCase
|
from django.test import TestCase
|
||||||
from django.test.client import RequestFactory
|
from django.test.client import RequestFactory
|
||||||
|
@ -49,7 +51,7 @@ class ClassBasedViewIntegrationTests(TestCase):
|
||||||
request = factory.post('/', 'f00bar', content_type='application/json')
|
request = factory.post('/', 'f00bar', content_type='application/json')
|
||||||
response = self.view(request)
|
response = self.view(request)
|
||||||
expected = {
|
expected = {
|
||||||
'detail': u'JSON parse error - No JSON object could be decoded'
|
'detail': 'JSON parse error - No JSON object could be decoded'
|
||||||
}
|
}
|
||||||
self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
|
self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
self.assertEquals(sanitise_json_error(response.data), expected)
|
self.assertEquals(sanitise_json_error(response.data), expected)
|
||||||
|
@ -64,7 +66,7 @@ class ClassBasedViewIntegrationTests(TestCase):
|
||||||
request = factory.post('/', form_data)
|
request = factory.post('/', form_data)
|
||||||
response = self.view(request)
|
response = self.view(request)
|
||||||
expected = {
|
expected = {
|
||||||
'detail': u'JSON parse error - No JSON object could be decoded'
|
'detail': 'JSON parse error - No JSON object could be decoded'
|
||||||
}
|
}
|
||||||
self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
|
self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
self.assertEquals(sanitise_json_error(response.data), expected)
|
self.assertEquals(sanitise_json_error(response.data), expected)
|
||||||
|
@ -78,7 +80,7 @@ class FunctionBasedViewIntegrationTests(TestCase):
|
||||||
request = factory.post('/', 'f00bar', content_type='application/json')
|
request = factory.post('/', 'f00bar', content_type='application/json')
|
||||||
response = self.view(request)
|
response = self.view(request)
|
||||||
expected = {
|
expected = {
|
||||||
'detail': u'JSON parse error - No JSON object could be decoded'
|
'detail': 'JSON parse error - No JSON object could be decoded'
|
||||||
}
|
}
|
||||||
self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
|
self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
self.assertEquals(sanitise_json_error(response.data), expected)
|
self.assertEquals(sanitise_json_error(response.data), expected)
|
||||||
|
@ -93,7 +95,7 @@ class FunctionBasedViewIntegrationTests(TestCase):
|
||||||
request = factory.post('/', form_data)
|
request = factory.post('/', form_data)
|
||||||
response = self.view(request)
|
response = self.view(request)
|
||||||
expected = {
|
expected = {
|
||||||
'detail': u'JSON parse error - No JSON object could be decoded'
|
'detail': 'JSON parse error - No JSON object could be decoded'
|
||||||
}
|
}
|
||||||
self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
|
self.assertEquals(response.status_code, status.HTTP_400_BAD_REQUEST)
|
||||||
self.assertEquals(sanitise_json_error(response.data), expected)
|
self.assertEquals(sanitise_json_error(response.data), expected)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.utils.encoding import smart_unicode
|
|
||||||
from django.utils.xmlutils import SimplerXMLGenerator
|
from django.utils.xmlutils import SimplerXMLGenerator
|
||||||
from rest_framework.compat import StringIO
|
from rest_framework.compat import StringIO
|
||||||
|
from rest_framework.compat import six
|
||||||
|
from rest_framework.compat import smart_text
|
||||||
import re
|
import re
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
|
|
||||||
|
@ -70,7 +71,7 @@ class XMLRenderer():
|
||||||
xml.endElement("list-item")
|
xml.endElement("list-item")
|
||||||
|
|
||||||
elif isinstance(data, dict):
|
elif isinstance(data, dict):
|
||||||
for key, value in data.iteritems():
|
for key, value in six.iteritems(data):
|
||||||
xml.startElement(key, {})
|
xml.startElement(key, {})
|
||||||
self._to_xml(xml, value)
|
self._to_xml(xml, value)
|
||||||
xml.endElement(key)
|
xml.endElement(key)
|
||||||
|
@ -80,10 +81,10 @@ class XMLRenderer():
|
||||||
pass
|
pass
|
||||||
|
|
||||||
else:
|
else:
|
||||||
xml.characters(smart_unicode(data))
|
xml.characters(smart_text(data))
|
||||||
|
|
||||||
def dict2xml(self, data):
|
def dict2xml(self, data):
|
||||||
stream = StringIO.StringIO()
|
stream = StringIO()
|
||||||
|
|
||||||
xml = SimplerXMLGenerator(stream, "utf-8")
|
xml = SimplerXMLGenerator(stream, "utf-8")
|
||||||
xml.startDocument()
|
xml.startDocument()
|
||||||
|
|
|
@ -47,7 +47,7 @@ class _MediaType(object):
|
||||||
if media_type_str is None:
|
if media_type_str is None:
|
||||||
media_type_str = ''
|
media_type_str = ''
|
||||||
self.orig = media_type_str
|
self.orig = media_type_str
|
||||||
self.full_type, self.params = parse_header(media_type_str)
|
self.full_type, self.params = parse_header(media_type_str.encode('iso-8859-1'))
|
||||||
self.main_type, sep, self.sub_type = self.full_type.partition('/')
|
self.main_type, sep, self.sub_type = self.full_type.partition('/')
|
||||||
|
|
||||||
def match(self, other):
|
def match(self, other):
|
||||||
|
|
9
setup.py
9
setup.py
|
@ -1,6 +1,8 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
# -*- coding: utf-8 -*-
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
#from __future__ import unicode_literals
|
||||||
|
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
import re
|
import re
|
||||||
import os
|
import os
|
||||||
|
@ -45,9 +47,9 @@ version = get_version('rest_framework')
|
||||||
|
|
||||||
if sys.argv[-1] == 'publish':
|
if sys.argv[-1] == 'publish':
|
||||||
os.system("python setup.py sdist upload")
|
os.system("python setup.py sdist upload")
|
||||||
print "You probably want to also tag the version now:"
|
print("You probably want to also tag the version now:")
|
||||||
print " git tag -a %s -m 'version %s'" % (version, version)
|
print(" git tag -a %s -m 'version %s'" % (version, version))
|
||||||
print " git push --tags"
|
print(" git push --tags")
|
||||||
sys.exit()
|
sys.exit()
|
||||||
|
|
||||||
|
|
||||||
|
@ -72,6 +74,7 @@ setup(
|
||||||
'License :: OSI Approved :: BSD License',
|
'License :: OSI Approved :: BSD License',
|
||||||
'Operating System :: OS Independent',
|
'Operating System :: OS Independent',
|
||||||
'Programming Language :: Python',
|
'Programming Language :: Python',
|
||||||
|
'Programming Language :: Python :: 3',
|
||||||
'Topic :: Internet :: WWW/HTTP',
|
'Topic :: Internet :: WWW/HTTP',
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user