Commit f2852811 by Tom Christie

Getting tests passing

parent ec096a1c
......@@ -19,11 +19,12 @@ class AuthTokenSerializer(serializers.Serializer):
if not user.is_active:
msg = _('User account is disabled.')
raise serializers.ValidationError(msg)
attrs['user'] = user
return attrs
else:
msg = _('Unable to login with provided credentials.')
raise serializers.ValidationError(msg)
else:
msg = _('Must include "username" and "password"')
raise serializers.ValidationError(msg)
attrs['user'] = user
return attrs
......@@ -18,7 +18,8 @@ class ObtainAuthToken(APIView):
def post(self, request):
serializer = self.serializer_class(data=request.DATA)
if serializer.is_valid():
token, created = Token.objects.get_or_create(user=serializer.object['user'])
user = serializer.validated_data['user']
token, created = Token.objects.get_or_create(user=user)
return Response({'token': token.key})
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
......
from rest_framework.utils import html
import inspect
class empty:
......@@ -11,6 +12,22 @@ class empty:
pass
def is_simple_callable(obj):
"""
True if the object is a callable that takes no arguments.
"""
function = inspect.isfunction(obj)
method = inspect.ismethod(obj)
if not (function or method):
return False
args, _, _, defaults = inspect.getargspec(obj)
len_args = len(args) if function else len(args) - 1
len_defaults = len(defaults) if defaults else 0
return len_args <= len_defaults
def get_attribute(instance, attrs):
"""
Similar to Python's built in `getattr(instance, attr)`,
......@@ -98,6 +115,7 @@ class Field(object):
self.field_name = field_name
self.parent = parent
self.root = root
self.context = parent.context
# `self.label` should deafult to being based on the field name.
if self.label is None:
......@@ -297,25 +315,55 @@ class IntegerField(Field):
self.fail('invalid_integer')
return data
def to_primative(self, value):
if value is None:
return None
return int(value)
class EmailField(CharField):
pass # TODO
class URLField(CharField):
pass # TODO
class RegexField(CharField):
def __init__(self, **kwargs):
self.regex = kwargs.pop('regex')
super(CharField, self).__init__(**kwargs)
class DateField(CharField):
def __init__(self, **kwargs):
self.input_formats = kwargs.pop('input_formats', None)
super(DateField, self).__init__(**kwargs)
class TimeField(CharField):
def __init__(self, **kwargs):
self.input_formats = kwargs.pop('input_formats', None)
super(TimeField, self).__init__(**kwargs)
class DateTimeField(CharField):
pass # TODO
def __init__(self, **kwargs):
self.input_formats = kwargs.pop('input_formats', None)
super(DateTimeField, self).__init__(**kwargs)
class FileField(Field):
pass # TODO
class ReadOnlyField(Field):
def to_primative(self, value):
if is_simple_callable(value):
return value()
return value
class MethodField(Field):
def __init__(self, **kwargs):
kwargs['source'] = '*'
......
......@@ -13,23 +13,6 @@ from rest_framework.request import clone_request
from rest_framework.settings import api_settings
def _get_validation_exclusions(obj, lookup_field=None):
"""
Given a model instance, and an optional pk and slug field,
return the full list of all other field names on that model.
For use when performing full_clean on a model instance,
so we only clean the required fields.
"""
if lookup_field == 'pk':
pk_field = obj._meta.pk
while pk_field.rel:
pk_field = pk_field.rel.to._meta.pk
lookup_field = pk_field.name
return [field.name for field in obj._meta.fields if field.name != lookup_field]
class CreateModelMixin(object):
"""
Create a model instance.
......@@ -92,15 +75,14 @@ class UpdateModelMixin(object):
if not serializer.is_valid():
return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
lookup_value = self.kwargs[lookup_url_kwarg]
extras = {self.lookup_field: lookup_value}
if self.object is None:
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
lookup_value = self.kwargs[lookup_url_kwarg]
extras = {self.lookup_field: lookup_value}
self.object = serializer.save(extras=extras)
return Response(serializer.data, status=status.HTTP_201_CREATED)
self.object = serializer.save(extras=extras)
self.object = serializer.save()
return Response(serializer.data, status=status.HTTP_200_OK)
def partial_update(self, request, *args, **kwargs):
......@@ -122,21 +104,6 @@ class UpdateModelMixin(object):
# return a 404 response.
raise
def pre_save(self, obj):
"""
Set any attributes on the object that are implicit in the request.
"""
lookup_url_kwarg = self.lookup_url_kwarg or self.lookup_field
lookup_value = self.kwargs[lookup_url_kwarg]
setattr(obj, self.lookup_field, lookup_value)
# Ensure we clean the attributes so that we don't eg return integer
# pk using a string representation, as provided by the url conf kwarg.
if hasattr(obj, 'full_clean'):
exclude = _get_validation_exclusions(obj, self.lookup_field)
obj.full_clean(exclude)
class DestroyModelMixin(object):
"""
......
......@@ -13,7 +13,7 @@ class NextPageField(serializers.Field):
"""
page_field = 'page'
def to_native(self, value):
def to_primative(self, value):
if not value.has_next():
return None
page = value.next_page_number()
......@@ -28,7 +28,7 @@ class PreviousPageField(serializers.Field):
"""
page_field = 'page'
def to_native(self, value):
def to_primative(self, value):
if not value.has_previous():
return None
page = value.previous_page_number()
......@@ -48,25 +48,11 @@ class DefaultObjectSerializer(serializers.Field):
super(DefaultObjectSerializer, self).__init__(source=source)
# class PaginationSerializerOptions(serializers.SerializerOptions):
# """
# An object that stores the options that may be provided to a
# pagination serializer by using the inner `Meta` class.
# Accessible on the instance as `serializer.opts`.
# """
# def __init__(self, meta):
# super(PaginationSerializerOptions, self).__init__(meta)
# self.object_serializer_class = getattr(meta, 'object_serializer_class',
# DefaultObjectSerializer)
class BasePaginationSerializer(serializers.Serializer):
"""
A base class for pagination serializers to inherit from,
to make implementing custom serializers more easy.
"""
# _options_class = PaginationSerializerOptions
results_field = 'results'
def __init__(self, *args, **kwargs):
......@@ -75,14 +61,16 @@ class BasePaginationSerializer(serializers.Serializer):
"""
super(BasePaginationSerializer, self).__init__(*args, **kwargs)
results_field = self.results_field
object_serializer = self.opts.object_serializer_class
if 'context' in kwargs:
context_kwarg = {'context': kwargs['context']}
else:
context_kwarg = {}
self.fields[results_field] = object_serializer(source='object_list', **context_kwarg)
try:
object_serializer = self.Meta.object_serializer_class
except AttributeError:
object_serializer = DefaultObjectSerializer
self.fields[results_field] = serializers.ListSerializer(
child=object_serializer(),
source='object_list'
)
self.fields[results_field].bind(results_field, self, self) # TODO: Support automatic binding
class PaginationSerializer(BasePaginationSerializer):
......
......@@ -73,7 +73,7 @@ class HyperlinkedRelatedField(RelatedField):
try:
http_prefix = value.startswith(('http:', 'https:'))
except AttributeError:
self.fail('incorrect_type', type(value).__name__)
self.fail('incorrect_type', data_type=type(value).__name__)
if http_prefix:
# If needed convert absolute URLs to relative path
......
......@@ -142,7 +142,7 @@ class Serializer(BaseSerializer):
return super(Serializer, cls).__new__(cls)
def __init__(self, *args, **kwargs):
kwargs.pop('context', None)
self.context = kwargs.pop('context', {})
kwargs.pop('partial', None)
kwargs.pop('many', False)
......@@ -202,7 +202,7 @@ class Serializer(BaseSerializer):
if errors:
raise ValidationError(errors)
return ret
return self.validate(ret)
def to_primative(self, instance):
"""
......@@ -217,6 +217,9 @@ class Serializer(BaseSerializer):
return ret
def validate(self, attrs):
return attrs
def __iter__(self):
errors = self.errors if hasattr(self, '_errors') else {}
for field in self.fields.values():
......@@ -232,8 +235,7 @@ class ListSerializer(BaseSerializer):
def __init__(self, *args, **kwargs):
self.child = kwargs.pop('child', copy.deepcopy(self.child))
assert self.child is not None, '`child` is a required argument.'
kwargs.pop('context', None)
self.context = kwargs.pop('context', {})
kwargs.pop('partial', None)
super(ListSerializer, self).__init__(*args, **kwargs)
......@@ -316,19 +318,19 @@ class ModelSerializer(Serializer):
models.PositiveIntegerField: IntegerField,
models.SmallIntegerField: IntegerField,
models.PositiveSmallIntegerField: IntegerField,
# models.DateTimeField: DateTimeField,
# models.DateField: DateField,
# models.TimeField: TimeField,
models.DateTimeField: DateTimeField,
models.DateField: DateField,
models.TimeField: TimeField,
# models.DecimalField: DecimalField,
# models.EmailField: EmailField,
models.EmailField: EmailField,
models.CharField: CharField,
# models.URLField: URLField,
models.URLField: URLField,
# models.SlugField: SlugField,
models.TextField: CharField,
models.CommaSeparatedIntegerField: CharField,
models.BooleanField: BooleanField,
models.NullBooleanField: BooleanField,
# models.FileField: FileField,
models.FileField: FileField,
# models.ImageField: ImageField,
}
......@@ -338,6 +340,15 @@ class ModelSerializer(Serializer):
self.opts = self._options_class(self.Meta)
super(ModelSerializer, self).__init__(*args, **kwargs)
def create(self):
ModelClass = self.opts.model
return ModelClass.objects.create(**self.validated_data)
def update(self, obj):
for attr, value in self.validated_data.items():
setattr(obj, attr, value)
obj.save()
def get_fields(self):
# Get the explicitly declared fields.
fields = copy.deepcopy(self.base_fields)
......@@ -566,8 +577,8 @@ class HyperlinkedModelSerializerOptions(ModelSerializerOptions):
class HyperlinkedModelSerializer(ModelSerializer):
_options_class = HyperlinkedModelSerializerOptions
_default_view_name = '%(model_name)s-detail'
# _hyperlink_field_class = HyperlinkedRelatedField
# _hyperlink_identify_field_class = HyperlinkedIdentityField
_hyperlink_field_class = HyperlinkedRelatedField
_hyperlink_identify_field_class = HyperlinkedIdentityField
def get_default_fields(self):
fields = super(HyperlinkedModelSerializer, self).get_default_fields()
......@@ -575,15 +586,15 @@ class HyperlinkedModelSerializer(ModelSerializer):
if self.opts.view_name is None:
self.opts.view_name = self._get_default_view_name(self.opts.model)
# if self.opts.url_field_name not in fields:
# url_field = self._hyperlink_identify_field_class(
# view_name=self.opts.view_name,
# lookup_field=self.opts.lookup_field
# )
# ret = self._dict_class()
# ret[self.opts.url_field_name] = url_field
# ret.update(fields)
# fields = ret
if self.opts.url_field_name not in fields:
url_field = self._hyperlink_identify_field_class(
view_name=self.opts.view_name,
lookup_field=self.opts.lookup_field
)
ret = fields.__class__()
ret[self.opts.url_field_name] = url_field
ret.update(fields)
fields = ret
return fields
......
"""
General serializer field tests.
"""
from __future__ import unicode_literals
# """
# General serializer field tests.
# """
# from __future__ import unicode_literals
import datetime
import re
from decimal import Decimal
from uuid import uuid4
from django.core import validators
from django.db import models
from django.test import TestCase
from django.utils.datastructures import SortedDict
from rest_framework import serializers
from tests.models import RESTFrameworkModel
# import datetime
# import re
# from decimal import Decimal
# from uuid import uuid4
# from django.core import validators
# from django.db import models
# from django.test import TestCase
# from django.utils.datastructures import SortedDict
# from rest_framework import serializers
# from tests.models import RESTFrameworkModel
class TimestampedModel(models.Model):
added = models.DateTimeField(auto_now_add=True)
updated = models.DateTimeField(auto_now=True)
# class TimestampedModel(models.Model):
# added = models.DateTimeField(auto_now_add=True)
# updated = models.DateTimeField(auto_now=True)
class CharPrimaryKeyModel(models.Model):
id = models.CharField(max_length=20, primary_key=True)
# class CharPrimaryKeyModel(models.Model):
# id = models.CharField(max_length=20, primary_key=True)
class TimestampedModelSerializer(serializers.ModelSerializer):
class Meta:
model = TimestampedModel
# class TimestampedModelSerializer(serializers.ModelSerializer):
# class Meta:
# model = TimestampedModel
class CharPrimaryKeyModelSerializer(serializers.ModelSerializer):
class Meta:
model = CharPrimaryKeyModel
# class CharPrimaryKeyModelSerializer(serializers.ModelSerializer):
# class Meta:
# model = CharPrimaryKeyModel
class TimeFieldModel(models.Model):
clock = models.TimeField()
# class TimeFieldModel(models.Model):
# clock = models.TimeField()
class TimeFieldModelSerializer(serializers.ModelSerializer):
class Meta:
model = TimeFieldModel
# class TimeFieldModelSerializer(serializers.ModelSerializer):
# class Meta:
# model = TimeFieldModel
SAMPLE_CHOICES = [
('red', 'Red'),
('green', 'Green'),
('blue', 'Blue'),
]
# SAMPLE_CHOICES = [
# ('red', 'Red'),
# ('green', 'Green'),
# ('blue', 'Blue'),
# ]
class ChoiceFieldModel(models.Model):
choice = models.CharField(choices=SAMPLE_CHOICES, blank=True, max_length=255)
# class ChoiceFieldModel(models.Model):
# choice = models.CharField(choices=SAMPLE_CHOICES, blank=True, max_length=255)
class ChoiceFieldModelSerializer(serializers.ModelSerializer):
class Meta:
model = ChoiceFieldModel
class ChoiceFieldModelWithNull(models.Model):
choice = models.CharField(choices=SAMPLE_CHOICES, blank=True, null=True, max_length=255)
class ChoiceFieldModelWithNullSerializer(serializers.ModelSerializer):
class Meta:
model = ChoiceFieldModelWithNull
class BasicFieldTests(TestCase):
def test_auto_now_fields_read_only(self):
"""
auto_now and auto_now_add fields should be read_only by default.
"""
serializer = TimestampedModelSerializer()
self.assertEqual(serializer.fields['added'].read_only, True)
def test_auto_pk_fields_read_only(self):
"""
AutoField fields should be read_only by default.
"""
serializer = TimestampedModelSerializer()
self.assertEqual(serializer.fields['id'].read_only, True)
def test_non_auto_pk_fields_not_read_only(self):
"""
PK fields other than AutoField fields should not be read_only by default.
"""
serializer = CharPrimaryKeyModelSerializer()
self.assertEqual(serializer.fields['id'].read_only, False)
def test_dict_field_ordering(self):
"""
Field should preserve dictionary ordering, if it exists.
See: https://github.com/tomchristie/django-rest-framework/issues/832
"""
ret = SortedDict()
ret['c'] = 1
ret['b'] = 1
ret['a'] = 1
ret['z'] = 1
field = serializers.Field()
keys = list(field.to_native(ret).keys())
self.assertEqual(keys, ['c', 'b', 'a', 'z'])
def test_widget_html_attributes(self):
"""
Make sure widget_html() renders the correct attributes
"""
r = re.compile('(\S+)=["\']?((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)["\']?')
form = TimeFieldModelSerializer().data
attributes = r.findall(form.fields['clock'].widget_html())
self.assertIn(('name', 'clock'), attributes)
self.assertIn(('id', 'clock'), attributes)
# class ChoiceFieldModelSerializer(serializers.ModelSerializer):
# class Meta:
# model = ChoiceFieldModel
# class ChoiceFieldModelWithNull(models.Model):
# choice = models.CharField(choices=SAMPLE_CHOICES, blank=True, null=True, max_length=255)
# class ChoiceFieldModelWithNullSerializer(serializers.ModelSerializer):
# class Meta:
# model = ChoiceFieldModelWithNull
# class BasicFieldTests(TestCase):
# def test_auto_now_fields_read_only(self):
# """
# auto_now and auto_now_add fields should be read_only by default.
# """
# serializer = TimestampedModelSerializer()
# self.assertEqual(serializer.fields['added'].read_only, True)
# def test_auto_pk_fields_read_only(self):
# """
# AutoField fields should be read_only by default.
# """
# serializer = TimestampedModelSerializer()
# self.assertEqual(serializer.fields['id'].read_only, True)
# def test_non_auto_pk_fields_not_read_only(self):
# """
# PK fields other than AutoField fields should not be read_only by default.
# """
# serializer = CharPrimaryKeyModelSerializer()
# self.assertEqual(serializer.fields['id'].read_only, False)
# def test_dict_field_ordering(self):
# """
# Field should preserve dictionary ordering, if it exists.
# See: https://github.com/tomchristie/django-rest-framework/issues/832
# """
# ret = SortedDict()
# ret['c'] = 1
# ret['b'] = 1
# ret['a'] = 1
# ret['z'] = 1
# field = serializers.Field()
# keys = list(field.to_native(ret).keys())
# self.assertEqual(keys, ['c', 'b', 'a', 'z'])
# def test_widget_html_attributes(self):
# """
# Make sure widget_html() renders the correct attributes
# """
# r = re.compile('(\S+)=["\']?((?:.(?!["\']?\s+(?:\S+)=|[>"\']))+.)["\']?')
# form = TimeFieldModelSerializer().data
# attributes = r.findall(form.fields['clock'].widget_html())
# self.assertIn(('name', 'clock'), attributes)
# self.assertIn(('id', 'clock'), attributes)
class DateFieldTest(TestCase):
"""
Tests for the DateFieldTest from_native() and to_native() behavior
"""
def test_from_native_string(self):
"""
Make sure from_native() accepts default iso input formats.
"""
f = serializers.DateField()
result_1 = f.from_native('1984-07-31')
self.assertEqual(datetime.date(1984, 7, 31), result_1)
def test_from_native_datetime_date(self):
"""
Make sure from_native() accepts a datetime.date instance.
"""
f = serializers.DateField()
result_1 = f.from_native(datetime.date(1984, 7, 31))
self.assertEqual(result_1, datetime.date(1984, 7, 31))
def test_from_native_custom_format(self):
"""
Make sure from_native() accepts custom input formats.
"""
f = serializers.DateField(input_formats=['%Y -- %d'])
result = f.from_native('1984 -- 31')
self.assertEqual(datetime.date(1984, 1, 31), result)
def test_from_native_invalid_default_on_custom_format(self):
"""
Make sure from_native() don't accept default formats if custom format is preset
"""
f = serializers.DateField(input_formats=['%Y -- %d'])
try:
f.from_native('1984-07-31')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY -- DD"])
else:
self.fail("ValidationError was not properly raised")
def test_from_native_empty(self):
"""
Make sure from_native() returns None on empty param.
"""
f = serializers.DateField()
result = f.from_native('')
self.assertEqual(result, None)
def test_from_native_none(self):
"""
Make sure from_native() returns None on None param.
"""
f = serializers.DateField()
result = f.from_native(None)
self.assertEqual(result, None)
def test_from_native_invalid_date(self):
"""
Make sure from_native() raises a ValidationError on passing an invalid date.
"""
f = serializers.DateField()
try:
f.from_native('1984-13-31')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]"])
else:
self.fail("ValidationError was not properly raised")
def test_from_native_invalid_format(self):
"""
Make sure from_native() raises a ValidationError on passing an invalid format.
"""
f = serializers.DateField()
try:
f.from_native('1984 -- 31')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]"])
else:
self.fail("ValidationError was not properly raised")
def test_to_native(self):
"""
Make sure to_native() returns datetime as default.
"""
f = serializers.DateField()
result_1 = f.to_native(datetime.date(1984, 7, 31))
self.assertEqual(datetime.date(1984, 7, 31), result_1)
def test_to_native_iso(self):
"""
Make sure to_native() with 'iso-8601' returns iso formated date.
"""
f = serializers.DateField(format='iso-8601')
result_1 = f.to_native(datetime.date(1984, 7, 31))
self.assertEqual('1984-07-31', result_1)
def test_to_native_custom_format(self):
"""
Make sure to_native() returns correct custom format.
"""
f = serializers.DateField(format="%Y - %m.%d")
result_1 = f.to_native(datetime.date(1984, 7, 31))
self.assertEqual('1984 - 07.31', result_1)
def test_to_native_none(self):
"""
Make sure from_native() returns None on None param.
"""
f = serializers.DateField(required=False)
self.assertEqual(None, f.to_native(None))
class DateTimeFieldTest(TestCase):
"""
Tests for the DateTimeField from_native() and to_native() behavior
"""
def test_from_native_string(self):
"""
Make sure from_native() accepts default iso input formats.
"""
f = serializers.DateTimeField()
result_1 = f.from_native('1984-07-31 04:31')
result_2 = f.from_native('1984-07-31 04:31:59')
result_3 = f.from_native('1984-07-31 04:31:59.000200')
self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31), result_1)
self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59), result_2)
self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59, 200), result_3)
def test_from_native_datetime_datetime(self):
"""
Make sure from_native() accepts a datetime.datetime instance.
"""
f = serializers.DateTimeField()
result_1 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31))
result_2 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31, 59))
result_3 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
self.assertEqual(result_1, datetime.datetime(1984, 7, 31, 4, 31))
self.assertEqual(result_2, datetime.datetime(1984, 7, 31, 4, 31, 59))
self.assertEqual(result_3, datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
def test_from_native_custom_format(self):
"""
Make sure from_native() accepts custom input formats.
"""
f = serializers.DateTimeField(input_formats=['%Y -- %H:%M'])
result = f.from_native('1984 -- 04:59')
self.assertEqual(datetime.datetime(1984, 1, 1, 4, 59), result)
def test_from_native_invalid_default_on_custom_format(self):
"""
Make sure from_native() don't accept default formats if custom format is preset
"""
f = serializers.DateTimeField(input_formats=['%Y -- %H:%M'])
try:
f.from_native('1984-07-31 04:31:59')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: YYYY -- hh:mm"])
else:
self.fail("ValidationError was not properly raised")
def test_from_native_empty(self):
"""
Make sure from_native() returns None on empty param.
"""
f = serializers.DateTimeField()
result = f.from_native('')
self.assertEqual(result, None)
def test_from_native_none(self):
"""
Make sure from_native() returns None on None param.
"""
f = serializers.DateTimeField()
result = f.from_native(None)
self.assertEqual(result, None)
def test_from_native_invalid_datetime(self):
"""
Make sure from_native() raises a ValidationError on passing an invalid datetime.
"""
f = serializers.DateTimeField()
try:
f.from_native('04:61:59')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: "
"YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]"])
else:
self.fail("ValidationError was not properly raised")
def test_from_native_invalid_format(self):
"""
Make sure from_native() raises a ValidationError on passing an invalid format.
"""
f = serializers.DateTimeField()
try:
f.from_native('04 -- 31')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: "
"YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]"])
else:
self.fail("ValidationError was not properly raised")
def test_to_native(self):
"""
Make sure to_native() returns isoformat as default.
"""
f = serializers.DateTimeField()
result_1 = f.to_native(datetime.datetime(1984, 7, 31))
result_2 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31))
result_3 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59))
result_4 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
self.assertEqual(datetime.datetime(1984, 7, 31), result_1)
self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31), result_2)
self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59), result_3)
self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59, 200), result_4)
def test_to_native_iso(self):
"""
Make sure to_native() with format=iso-8601 returns iso formatted datetime.
"""
f = serializers.DateTimeField(format='iso-8601')
result_1 = f.to_native(datetime.datetime(1984, 7, 31))
result_2 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31))
result_3 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59))
result_4 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
self.assertEqual('1984-07-31T00:00:00', result_1)
self.assertEqual('1984-07-31T04:31:00', result_2)
self.assertEqual('1984-07-31T04:31:59', result_3)
self.assertEqual('1984-07-31T04:31:59.000200', result_4)
def test_to_native_custom_format(self):
"""
Make sure to_native() returns correct custom format.
"""
f = serializers.DateTimeField(format="%Y - %H:%M")
result_1 = f.to_native(datetime.datetime(1984, 7, 31))
result_2 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31))
result_3 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59))
result_4 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
self.assertEqual('1984 - 00:00', result_1)
self.assertEqual('1984 - 04:31', result_2)
self.assertEqual('1984 - 04:31', result_3)
self.assertEqual('1984 - 04:31', result_4)
def test_to_native_none(self):
"""
Make sure from_native() returns None on None param.
"""
f = serializers.DateTimeField(required=False)
self.assertEqual(None, f.to_native(None))
class TimeFieldTest(TestCase):
"""
Tests for the TimeField from_native() and to_native() behavior
"""
def test_from_native_string(self):
"""
Make sure from_native() accepts default iso input formats.
"""
f = serializers.TimeField()
result_1 = f.from_native('04:31')
result_2 = f.from_native('04:31:59')
result_3 = f.from_native('04:31:59.000200')
self.assertEqual(datetime.time(4, 31), result_1)
self.assertEqual(datetime.time(4, 31, 59), result_2)
self.assertEqual(datetime.time(4, 31, 59, 200), result_3)
def test_from_native_datetime_time(self):
"""
Make sure from_native() accepts a datetime.time instance.
"""
f = serializers.TimeField()
result_1 = f.from_native(datetime.time(4, 31))
result_2 = f.from_native(datetime.time(4, 31, 59))
result_3 = f.from_native(datetime.time(4, 31, 59, 200))
self.assertEqual(result_1, datetime.time(4, 31))
self.assertEqual(result_2, datetime.time(4, 31, 59))
self.assertEqual(result_3, datetime.time(4, 31, 59, 200))
def test_from_native_custom_format(self):
"""
Make sure from_native() accepts custom input formats.
"""
f = serializers.TimeField(input_formats=['%H -- %M'])
result = f.from_native('04 -- 31')
self.assertEqual(datetime.time(4, 31), result)
def test_from_native_invalid_default_on_custom_format(self):
"""
Make sure from_native() don't accept default formats if custom format is preset
"""
f = serializers.TimeField(input_formats=['%H -- %M'])
try:
f.from_native('04:31:59')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: hh -- mm"])
else:
self.fail("ValidationError was not properly raised")
def test_from_native_empty(self):
"""
Make sure from_native() returns None on empty param.
"""
f = serializers.TimeField()
result = f.from_native('')
self.assertEqual(result, None)
def test_from_native_none(self):
"""
Make sure from_native() returns None on None param.
"""
f = serializers.TimeField()
result = f.from_native(None)
self.assertEqual(result, None)
def test_from_native_invalid_time(self):
"""
Make sure from_native() raises a ValidationError on passing an invalid time.
"""
f = serializers.TimeField()
try:
f.from_native('04:61:59')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: "
"hh:mm[:ss[.uuuuuu]]"])
else:
self.fail("ValidationError was not properly raised")
def test_from_native_invalid_format(self):
"""
Make sure from_native() raises a ValidationError on passing an invalid format.
"""
f = serializers.TimeField()
try:
f.from_native('04 -- 31')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: "
"hh:mm[:ss[.uuuuuu]]"])
else:
self.fail("ValidationError was not properly raised")
def test_to_native(self):
"""
Make sure to_native() returns time object as default.
"""
f = serializers.TimeField()
result_1 = f.to_native(datetime.time(4, 31))
result_2 = f.to_native(datetime.time(4, 31, 59))
result_3 = f.to_native(datetime.time(4, 31, 59, 200))
self.assertEqual(datetime.time(4, 31), result_1)
self.assertEqual(datetime.time(4, 31, 59), result_2)
self.assertEqual(datetime.time(4, 31, 59, 200), result_3)
def test_to_native_iso(self):
"""
Make sure to_native() with format='iso-8601' returns iso formatted time.
"""
f = serializers.TimeField(format='iso-8601')
result_1 = f.to_native(datetime.time(4, 31))
result_2 = f.to_native(datetime.time(4, 31, 59))
result_3 = f.to_native(datetime.time(4, 31, 59, 200))
self.assertEqual('04:31:00', result_1)
self.assertEqual('04:31:59', result_2)
self.assertEqual('04:31:59.000200', result_3)
def test_to_native_custom_format(self):
"""
Make sure to_native() returns correct custom format.
"""
f = serializers.TimeField(format="%H - %S [%f]")
result_1 = f.to_native(datetime.time(4, 31))
result_2 = f.to_native(datetime.time(4, 31, 59))
result_3 = f.to_native(datetime.time(4, 31, 59, 200))
self.assertEqual('04 - 00 [000000]', result_1)
self.assertEqual('04 - 59 [000000]', result_2)
self.assertEqual('04 - 59 [000200]', result_3)
class DecimalFieldTest(TestCase):
"""
Tests for the DecimalField from_native() and to_native() behavior
"""
def test_from_native_string(self):
"""
Make sure from_native() accepts string values
"""
f = serializers.DecimalField()
result_1 = f.from_native('9000')
result_2 = f.from_native('1.00000001')
self.assertEqual(Decimal('9000'), result_1)
self.assertEqual(Decimal('1.00000001'), result_2)
def test_from_native_invalid_string(self):
"""
Make sure from_native() raises ValidationError on passing invalid string
"""
f = serializers.DecimalField()
try:
f.from_native('123.45.6')
except validators.ValidationError as e:
self.assertEqual(e.messages, ["Enter a number."])
else:
self.fail("ValidationError was not properly raised")
def test_from_native_integer(self):
"""
Make sure from_native() accepts integer values
"""
f = serializers.DecimalField()
result = f.from_native(9000)
self.assertEqual(Decimal('9000'), result)
def test_from_native_float(self):
"""
Make sure from_native() accepts float values
"""
f = serializers.DecimalField()
result = f.from_native(1.00000001)
self.assertEqual(Decimal('1.00000001'), result)
def test_from_native_empty(self):
"""
Make sure from_native() returns None on empty param.
"""
f = serializers.DecimalField()
result = f.from_native('')
self.assertEqual(result, None)
def test_from_native_none(self):
"""
Make sure from_native() returns None on None param.
"""
f = serializers.DecimalField()
result = f.from_native(None)
self.assertEqual(result, None)
def test_to_native(self):
"""
Make sure to_native() returns Decimal as string.
"""
f = serializers.DecimalField()
result_1 = f.to_native(Decimal('9000'))
result_2 = f.to_native(Decimal('1.00000001'))
self.assertEqual(Decimal('9000'), result_1)
self.assertEqual(Decimal('1.00000001'), result_2)
def test_to_native_none(self):
"""
Make sure from_native() returns None on None param.
"""
f = serializers.DecimalField(required=False)
self.assertEqual(None, f.to_native(None))
def test_valid_serialization(self):
"""
Make sure the serializer works correctly
"""
class DecimalSerializer(serializers.Serializer):
decimal_field = serializers.DecimalField(max_value=9010,
min_value=9000,
max_digits=6,
decimal_places=2)
self.assertTrue(DecimalSerializer(data={'decimal_field': '9001'}).is_valid())
self.assertTrue(DecimalSerializer(data={'decimal_field': '9001.2'}).is_valid())
self.assertTrue(DecimalSerializer(data={'decimal_field': '9001.23'}).is_valid())
self.assertFalse(DecimalSerializer(data={'decimal_field': '8000'}).is_valid())
self.assertFalse(DecimalSerializer(data={'decimal_field': '9900'}).is_valid())
self.assertFalse(DecimalSerializer(data={'decimal_field': '9001.234'}).is_valid())
def test_raise_max_value(self):
"""
Make sure max_value violations raises ValidationError
"""
class DecimalSerializer(serializers.Serializer):
decimal_field = serializers.DecimalField(max_value=100)
s = DecimalSerializer(data={'decimal_field': '123'})
self.assertFalse(s.is_valid())
self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is less than or equal to 100.']})
def test_raise_min_value(self):
"""
Make sure min_value violations raises ValidationError
"""
class DecimalSerializer(serializers.Serializer):
decimal_field = serializers.DecimalField(min_value=100)
s = DecimalSerializer(data={'decimal_field': '99'})
self.assertFalse(s.is_valid())
self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is greater than or equal to 100.']})
def test_raise_max_digits(self):
"""
Make sure max_digits violations raises ValidationError
"""
class DecimalSerializer(serializers.Serializer):
decimal_field = serializers.DecimalField(max_digits=5)
s = DecimalSerializer(data={'decimal_field': '123.456'})
self.assertFalse(s.is_valid())
self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 5 digits in total.']})
def test_raise_max_decimal_places(self):
"""
Make sure max_decimal_places violations raises ValidationError
"""
class DecimalSerializer(serializers.Serializer):
decimal_field = serializers.DecimalField(decimal_places=3)
s = DecimalSerializer(data={'decimal_field': '123.4567'})
self.assertFalse(s.is_valid())
self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 3 decimal places.']})
def test_raise_max_whole_digits(self):
"""
Make sure max_whole_digits violations raises ValidationError
"""
class DecimalSerializer(serializers.Serializer):
decimal_field = serializers.DecimalField(max_digits=4, decimal_places=3)
s = DecimalSerializer(data={'decimal_field': '12345.6'})
self.assertFalse(s.is_valid())
self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']})
class ChoiceFieldTests(TestCase):
"""
Tests for the ChoiceField options generator
"""
def test_choices_required(self):
"""
Make sure proper choices are rendered if field is required
"""
f = serializers.ChoiceField(required=True, choices=SAMPLE_CHOICES)
self.assertEqual(f.choices, SAMPLE_CHOICES)
def test_choices_not_required(self):
"""
Make sure proper choices (plus blank) are rendered if the field isn't required
"""
f = serializers.ChoiceField(required=False, choices=SAMPLE_CHOICES)
self.assertEqual(f.choices, models.fields.BLANK_CHOICE_DASH + SAMPLE_CHOICES)
def test_blank_choice_display(self):
blank = 'No Preference'
f = serializers.ChoiceField(
required=False,
choices=SAMPLE_CHOICES,
blank_display_value=blank,
)
self.assertEqual(f.choices, [('', blank)] + SAMPLE_CHOICES)
def test_invalid_choice_model(self):
s = ChoiceFieldModelSerializer(data={'choice': 'wrong_value'})
self.assertFalse(s.is_valid())
self.assertEqual(s.errors, {'choice': ['Select a valid choice. wrong_value is not one of the available choices.']})
self.assertEqual(s.data['choice'], '')
def test_empty_choice_model(self):
"""
Test that the 'empty' value is correctly passed and used depending on
the 'null' property on the model field.
"""
s = ChoiceFieldModelSerializer(data={'choice': ''})
self.assertTrue(s.is_valid())
self.assertEqual(s.data['choice'], '')
s = ChoiceFieldModelWithNullSerializer(data={'choice': ''})
self.assertTrue(s.is_valid())
self.assertEqual(s.data['choice'], None)
def test_from_native_empty(self):
"""
Make sure from_native() returns an empty string on empty param by default.
"""
f = serializers.ChoiceField(choices=SAMPLE_CHOICES)
self.assertEqual(f.from_native(''), '')
self.assertEqual(f.from_native(None), '')
def test_from_native_empty_override(self):
"""
Make sure you can override from_native() behavior regarding empty values.
"""
f = serializers.ChoiceField(choices=SAMPLE_CHOICES, empty=None)
self.assertEqual(f.from_native(''), None)
self.assertEqual(f.from_native(None), None)
def test_metadata_choices(self):
"""
Make sure proper choices are included in the field's metadata.
"""
choices = [{'value': v, 'display_name': n} for v, n in SAMPLE_CHOICES]
f = serializers.ChoiceField(choices=SAMPLE_CHOICES)
self.assertEqual(f.metadata()['choices'], choices)
def test_metadata_choices_not_required(self):
"""
Make sure proper choices are included in the field's metadata.
"""
choices = [{'value': v, 'display_name': n}
for v, n in models.fields.BLANK_CHOICE_DASH + SAMPLE_CHOICES]
f = serializers.ChoiceField(required=False, choices=SAMPLE_CHOICES)
self.assertEqual(f.metadata()['choices'], choices)
class EmailFieldTests(TestCase):
"""
Tests for EmailField attribute values
"""
class EmailFieldModel(RESTFrameworkModel):
email_field = models.EmailField(blank=True)
class EmailFieldWithGivenMaxLengthModel(RESTFrameworkModel):
email_field = models.EmailField(max_length=150, blank=True)
def test_default_model_value(self):
class EmailFieldSerializer(serializers.ModelSerializer):
class Meta:
model = self.EmailFieldModel
serializer = EmailFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['email_field'], 'max_length'), 75)
def test_given_model_value(self):
class EmailFieldSerializer(serializers.ModelSerializer):
class Meta:
model = self.EmailFieldWithGivenMaxLengthModel
serializer = EmailFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['email_field'], 'max_length'), 150)
def test_given_serializer_value(self):
class EmailFieldSerializer(serializers.ModelSerializer):
email_field = serializers.EmailField(source='email_field', max_length=20, required=False)
class Meta:
model = self.EmailFieldModel
serializer = EmailFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['email_field'], 'max_length'), 20)
class SlugFieldTests(TestCase):
"""
Tests for SlugField attribute values
"""
class SlugFieldModel(RESTFrameworkModel):
slug_field = models.SlugField(blank=True)
class SlugFieldWithGivenMaxLengthModel(RESTFrameworkModel):
slug_field = models.SlugField(max_length=84, blank=True)
def test_default_model_value(self):
class SlugFieldSerializer(serializers.ModelSerializer):
class Meta:
model = self.SlugFieldModel
serializer = SlugFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['slug_field'], 'max_length'), 50)
def test_given_model_value(self):
class SlugFieldSerializer(serializers.ModelSerializer):
class Meta:
model = self.SlugFieldWithGivenMaxLengthModel
serializer = SlugFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['slug_field'], 'max_length'), 84)
def test_given_serializer_value(self):
class SlugFieldSerializer(serializers.ModelSerializer):
slug_field = serializers.SlugField(source='slug_field',
max_length=20, required=False)
class Meta:
model = self.SlugFieldModel
serializer = SlugFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['slug_field'],
'max_length'), 20)
def test_invalid_slug(self):
"""
Make sure an invalid slug raises ValidationError
"""
class SlugFieldSerializer(serializers.ModelSerializer):
slug_field = serializers.SlugField(source='slug_field', max_length=20, required=True)
# class DateFieldTest(TestCase):
# """
# Tests for the DateFieldTest from_native() and to_native() behavior
# """
# def test_from_native_string(self):
# """
# Make sure from_native() accepts default iso input formats.
# """
# f = serializers.DateField()
# result_1 = f.from_native('1984-07-31')
# self.assertEqual(datetime.date(1984, 7, 31), result_1)
# def test_from_native_datetime_date(self):
# """
# Make sure from_native() accepts a datetime.date instance.
# """
# f = serializers.DateField()
# result_1 = f.from_native(datetime.date(1984, 7, 31))
# self.assertEqual(result_1, datetime.date(1984, 7, 31))
# def test_from_native_custom_format(self):
# """
# Make sure from_native() accepts custom input formats.
# """
# f = serializers.DateField(input_formats=['%Y -- %d'])
# result = f.from_native('1984 -- 31')
# self.assertEqual(datetime.date(1984, 1, 31), result)
# def test_from_native_invalid_default_on_custom_format(self):
# """
# Make sure from_native() don't accept default formats if custom format is preset
# """
# f = serializers.DateField(input_formats=['%Y -- %d'])
# try:
# f.from_native('1984-07-31')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY -- DD"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_from_native_empty(self):
# """
# Make sure from_native() returns None on empty param.
# """
# f = serializers.DateField()
# result = f.from_native('')
# self.assertEqual(result, None)
# def test_from_native_none(self):
# """
# Make sure from_native() returns None on None param.
# """
# f = serializers.DateField()
# result = f.from_native(None)
# self.assertEqual(result, None)
# def test_from_native_invalid_date(self):
# """
# Make sure from_native() raises a ValidationError on passing an invalid date.
# """
# f = serializers.DateField()
# try:
# f.from_native('1984-13-31')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_from_native_invalid_format(self):
# """
# Make sure from_native() raises a ValidationError on passing an invalid format.
# """
# f = serializers.DateField()
# try:
# f.from_native('1984 -- 31')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Date has wrong format. Use one of these formats instead: YYYY[-MM[-DD]]"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_to_native(self):
# """
# Make sure to_native() returns datetime as default.
# """
# f = serializers.DateField()
# result_1 = f.to_native(datetime.date(1984, 7, 31))
# self.assertEqual(datetime.date(1984, 7, 31), result_1)
# def test_to_native_iso(self):
# """
# Make sure to_native() with 'iso-8601' returns iso formated date.
# """
# f = serializers.DateField(format='iso-8601')
# result_1 = f.to_native(datetime.date(1984, 7, 31))
# self.assertEqual('1984-07-31', result_1)
# def test_to_native_custom_format(self):
# """
# Make sure to_native() returns correct custom format.
# """
# f = serializers.DateField(format="%Y - %m.%d")
# result_1 = f.to_native(datetime.date(1984, 7, 31))
# self.assertEqual('1984 - 07.31', result_1)
# def test_to_native_none(self):
# """
# Make sure from_native() returns None on None param.
# """
# f = serializers.DateField(required=False)
# self.assertEqual(None, f.to_native(None))
# class DateTimeFieldTest(TestCase):
# """
# Tests for the DateTimeField from_native() and to_native() behavior
# """
# def test_from_native_string(self):
# """
# Make sure from_native() accepts default iso input formats.
# """
# f = serializers.DateTimeField()
# result_1 = f.from_native('1984-07-31 04:31')
# result_2 = f.from_native('1984-07-31 04:31:59')
# result_3 = f.from_native('1984-07-31 04:31:59.000200')
# self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31), result_1)
# self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59), result_2)
# self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59, 200), result_3)
# def test_from_native_datetime_datetime(self):
# """
# Make sure from_native() accepts a datetime.datetime instance.
# """
# f = serializers.DateTimeField()
# result_1 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31))
# result_2 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31, 59))
# result_3 = f.from_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
# self.assertEqual(result_1, datetime.datetime(1984, 7, 31, 4, 31))
# self.assertEqual(result_2, datetime.datetime(1984, 7, 31, 4, 31, 59))
# self.assertEqual(result_3, datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
# def test_from_native_custom_format(self):
# """
# Make sure from_native() accepts custom input formats.
# """
# f = serializers.DateTimeField(input_formats=['%Y -- %H:%M'])
# result = f.from_native('1984 -- 04:59')
# self.assertEqual(datetime.datetime(1984, 1, 1, 4, 59), result)
# def test_from_native_invalid_default_on_custom_format(self):
# """
# Make sure from_native() don't accept default formats if custom format is preset
# """
# f = serializers.DateTimeField(input_formats=['%Y -- %H:%M'])
# try:
# f.from_native('1984-07-31 04:31:59')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: YYYY -- hh:mm"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_from_native_empty(self):
# """
# Make sure from_native() returns None on empty param.
# """
# f = serializers.DateTimeField()
# result = f.from_native('')
# self.assertEqual(result, None)
# def test_from_native_none(self):
# """
# Make sure from_native() returns None on None param.
# """
# f = serializers.DateTimeField()
# result = f.from_native(None)
# self.assertEqual(result, None)
# def test_from_native_invalid_datetime(self):
# """
# Make sure from_native() raises a ValidationError on passing an invalid datetime.
# """
# f = serializers.DateTimeField()
# try:
# f.from_native('04:61:59')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: "
# "YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_from_native_invalid_format(self):
# """
# Make sure from_native() raises a ValidationError on passing an invalid format.
# """
# f = serializers.DateTimeField()
# try:
# f.from_native('04 -- 31')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Datetime has wrong format. Use one of these formats instead: "
# "YYYY-MM-DDThh:mm[:ss[.uuuuuu]][+HH:MM|-HH:MM|Z]"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_to_native(self):
# """
# Make sure to_native() returns isoformat as default.
# """
# f = serializers.DateTimeField()
# result_1 = f.to_native(datetime.datetime(1984, 7, 31))
# result_2 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31))
# result_3 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59))
# result_4 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
# self.assertEqual(datetime.datetime(1984, 7, 31), result_1)
# self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31), result_2)
# self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59), result_3)
# self.assertEqual(datetime.datetime(1984, 7, 31, 4, 31, 59, 200), result_4)
# def test_to_native_iso(self):
# """
# Make sure to_native() with format=iso-8601 returns iso formatted datetime.
# """
# f = serializers.DateTimeField(format='iso-8601')
# result_1 = f.to_native(datetime.datetime(1984, 7, 31))
# result_2 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31))
# result_3 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59))
# result_4 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
# self.assertEqual('1984-07-31T00:00:00', result_1)
# self.assertEqual('1984-07-31T04:31:00', result_2)
# self.assertEqual('1984-07-31T04:31:59', result_3)
# self.assertEqual('1984-07-31T04:31:59.000200', result_4)
# def test_to_native_custom_format(self):
# """
# Make sure to_native() returns correct custom format.
# """
# f = serializers.DateTimeField(format="%Y - %H:%M")
# result_1 = f.to_native(datetime.datetime(1984, 7, 31))
# result_2 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31))
# result_3 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59))
# result_4 = f.to_native(datetime.datetime(1984, 7, 31, 4, 31, 59, 200))
# self.assertEqual('1984 - 00:00', result_1)
# self.assertEqual('1984 - 04:31', result_2)
# self.assertEqual('1984 - 04:31', result_3)
# self.assertEqual('1984 - 04:31', result_4)
# def test_to_native_none(self):
# """
# Make sure from_native() returns None on None param.
# """
# f = serializers.DateTimeField(required=False)
# self.assertEqual(None, f.to_native(None))
# class TimeFieldTest(TestCase):
# """
# Tests for the TimeField from_native() and to_native() behavior
# """
# def test_from_native_string(self):
# """
# Make sure from_native() accepts default iso input formats.
# """
# f = serializers.TimeField()
# result_1 = f.from_native('04:31')
# result_2 = f.from_native('04:31:59')
# result_3 = f.from_native('04:31:59.000200')
# self.assertEqual(datetime.time(4, 31), result_1)
# self.assertEqual(datetime.time(4, 31, 59), result_2)
# self.assertEqual(datetime.time(4, 31, 59, 200), result_3)
# def test_from_native_datetime_time(self):
# """
# Make sure from_native() accepts a datetime.time instance.
# """
# f = serializers.TimeField()
# result_1 = f.from_native(datetime.time(4, 31))
# result_2 = f.from_native(datetime.time(4, 31, 59))
# result_3 = f.from_native(datetime.time(4, 31, 59, 200))
# self.assertEqual(result_1, datetime.time(4, 31))
# self.assertEqual(result_2, datetime.time(4, 31, 59))
# self.assertEqual(result_3, datetime.time(4, 31, 59, 200))
# def test_from_native_custom_format(self):
# """
# Make sure from_native() accepts custom input formats.
# """
# f = serializers.TimeField(input_formats=['%H -- %M'])
# result = f.from_native('04 -- 31')
# self.assertEqual(datetime.time(4, 31), result)
# def test_from_native_invalid_default_on_custom_format(self):
# """
# Make sure from_native() don't accept default formats if custom format is preset
# """
# f = serializers.TimeField(input_formats=['%H -- %M'])
# try:
# f.from_native('04:31:59')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: hh -- mm"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_from_native_empty(self):
# """
# Make sure from_native() returns None on empty param.
# """
# f = serializers.TimeField()
# result = f.from_native('')
# self.assertEqual(result, None)
# def test_from_native_none(self):
# """
# Make sure from_native() returns None on None param.
# """
# f = serializers.TimeField()
# result = f.from_native(None)
# self.assertEqual(result, None)
# def test_from_native_invalid_time(self):
# """
# Make sure from_native() raises a ValidationError on passing an invalid time.
# """
# f = serializers.TimeField()
# try:
# f.from_native('04:61:59')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: "
# "hh:mm[:ss[.uuuuuu]]"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_from_native_invalid_format(self):
# """
# Make sure from_native() raises a ValidationError on passing an invalid format.
# """
# f = serializers.TimeField()
# try:
# f.from_native('04 -- 31')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Time has wrong format. Use one of these formats instead: "
# "hh:mm[:ss[.uuuuuu]]"])
# else:
# self.fail("ValidationError was not properly raised")
# def test_to_native(self):
# """
# Make sure to_native() returns time object as default.
# """
# f = serializers.TimeField()
# result_1 = f.to_native(datetime.time(4, 31))
# result_2 = f.to_native(datetime.time(4, 31, 59))
# result_3 = f.to_native(datetime.time(4, 31, 59, 200))
# self.assertEqual(datetime.time(4, 31), result_1)
# self.assertEqual(datetime.time(4, 31, 59), result_2)
# self.assertEqual(datetime.time(4, 31, 59, 200), result_3)
# def test_to_native_iso(self):
# """
# Make sure to_native() with format='iso-8601' returns iso formatted time.
# """
# f = serializers.TimeField(format='iso-8601')
# result_1 = f.to_native(datetime.time(4, 31))
# result_2 = f.to_native(datetime.time(4, 31, 59))
# result_3 = f.to_native(datetime.time(4, 31, 59, 200))
# self.assertEqual('04:31:00', result_1)
# self.assertEqual('04:31:59', result_2)
# self.assertEqual('04:31:59.000200', result_3)
# def test_to_native_custom_format(self):
# """
# Make sure to_native() returns correct custom format.
# """
# f = serializers.TimeField(format="%H - %S [%f]")
# result_1 = f.to_native(datetime.time(4, 31))
# result_2 = f.to_native(datetime.time(4, 31, 59))
# result_3 = f.to_native(datetime.time(4, 31, 59, 200))
# self.assertEqual('04 - 00 [000000]', result_1)
# self.assertEqual('04 - 59 [000000]', result_2)
# self.assertEqual('04 - 59 [000200]', result_3)
# class DecimalFieldTest(TestCase):
# """
# Tests for the DecimalField from_native() and to_native() behavior
# """
# def test_from_native_string(self):
# """
# Make sure from_native() accepts string values
# """
# f = serializers.DecimalField()
# result_1 = f.from_native('9000')
# result_2 = f.from_native('1.00000001')
# self.assertEqual(Decimal('9000'), result_1)
# self.assertEqual(Decimal('1.00000001'), result_2)
# def test_from_native_invalid_string(self):
# """
# Make sure from_native() raises ValidationError on passing invalid string
# """
# f = serializers.DecimalField()
# try:
# f.from_native('123.45.6')
# except validators.ValidationError as e:
# self.assertEqual(e.messages, ["Enter a number."])
# else:
# self.fail("ValidationError was not properly raised")
# def test_from_native_integer(self):
# """
# Make sure from_native() accepts integer values
# """
# f = serializers.DecimalField()
# result = f.from_native(9000)
# self.assertEqual(Decimal('9000'), result)
# def test_from_native_float(self):
# """
# Make sure from_native() accepts float values
# """
# f = serializers.DecimalField()
# result = f.from_native(1.00000001)
# self.assertEqual(Decimal('1.00000001'), result)
# def test_from_native_empty(self):
# """
# Make sure from_native() returns None on empty param.
# """
# f = serializers.DecimalField()
# result = f.from_native('')
# self.assertEqual(result, None)
# def test_from_native_none(self):
# """
# Make sure from_native() returns None on None param.
# """
# f = serializers.DecimalField()
# result = f.from_native(None)
# self.assertEqual(result, None)
# def test_to_native(self):
# """
# Make sure to_native() returns Decimal as string.
# """
# f = serializers.DecimalField()
# result_1 = f.to_native(Decimal('9000'))
# result_2 = f.to_native(Decimal('1.00000001'))
# self.assertEqual(Decimal('9000'), result_1)
# self.assertEqual(Decimal('1.00000001'), result_2)
# def test_to_native_none(self):
# """
# Make sure from_native() returns None on None param.
# """
# f = serializers.DecimalField(required=False)
# self.assertEqual(None, f.to_native(None))
# def test_valid_serialization(self):
# """
# Make sure the serializer works correctly
# """
# class DecimalSerializer(serializers.Serializer):
# decimal_field = serializers.DecimalField(max_value=9010,
# min_value=9000,
# max_digits=6,
# decimal_places=2)
# self.assertTrue(DecimalSerializer(data={'decimal_field': '9001'}).is_valid())
# self.assertTrue(DecimalSerializer(data={'decimal_field': '9001.2'}).is_valid())
# self.assertTrue(DecimalSerializer(data={'decimal_field': '9001.23'}).is_valid())
# self.assertFalse(DecimalSerializer(data={'decimal_field': '8000'}).is_valid())
# self.assertFalse(DecimalSerializer(data={'decimal_field': '9900'}).is_valid())
# self.assertFalse(DecimalSerializer(data={'decimal_field': '9001.234'}).is_valid())
# def test_raise_max_value(self):
# """
# Make sure max_value violations raises ValidationError
# """
# class DecimalSerializer(serializers.Serializer):
# decimal_field = serializers.DecimalField(max_value=100)
# s = DecimalSerializer(data={'decimal_field': '123'})
# self.assertFalse(s.is_valid())
# self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is less than or equal to 100.']})
# def test_raise_min_value(self):
# """
# Make sure min_value violations raises ValidationError
# """
# class DecimalSerializer(serializers.Serializer):
# decimal_field = serializers.DecimalField(min_value=100)
# s = DecimalSerializer(data={'decimal_field': '99'})
# self.assertFalse(s.is_valid())
# self.assertEqual(s.errors, {'decimal_field': ['Ensure this value is greater than or equal to 100.']})
# def test_raise_max_digits(self):
# """
# Make sure max_digits violations raises ValidationError
# """
# class DecimalSerializer(serializers.Serializer):
# decimal_field = serializers.DecimalField(max_digits=5)
# s = DecimalSerializer(data={'decimal_field': '123.456'})
# self.assertFalse(s.is_valid())
# self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 5 digits in total.']})
# def test_raise_max_decimal_places(self):
# """
# Make sure max_decimal_places violations raises ValidationError
# """
# class DecimalSerializer(serializers.Serializer):
# decimal_field = serializers.DecimalField(decimal_places=3)
# s = DecimalSerializer(data={'decimal_field': '123.4567'})
# self.assertFalse(s.is_valid())
# self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 3 decimal places.']})
# def test_raise_max_whole_digits(self):
# """
# Make sure max_whole_digits violations raises ValidationError
# """
# class DecimalSerializer(serializers.Serializer):
# decimal_field = serializers.DecimalField(max_digits=4, decimal_places=3)
# s = DecimalSerializer(data={'decimal_field': '12345.6'})
# self.assertFalse(s.is_valid())
# self.assertEqual(s.errors, {'decimal_field': ['Ensure that there are no more than 4 digits in total.']})
# class ChoiceFieldTests(TestCase):
# """
# Tests for the ChoiceField options generator
# """
# def test_choices_required(self):
# """
# Make sure proper choices are rendered if field is required
# """
# f = serializers.ChoiceField(required=True, choices=SAMPLE_CHOICES)
# self.assertEqual(f.choices, SAMPLE_CHOICES)
# def test_choices_not_required(self):
# """
# Make sure proper choices (plus blank) are rendered if the field isn't required
# """
# f = serializers.ChoiceField(required=False, choices=SAMPLE_CHOICES)
# self.assertEqual(f.choices, models.fields.BLANK_CHOICE_DASH + SAMPLE_CHOICES)
# def test_blank_choice_display(self):
# blank = 'No Preference'
# f = serializers.ChoiceField(
# required=False,
# choices=SAMPLE_CHOICES,
# blank_display_value=blank,
# )
# self.assertEqual(f.choices, [('', blank)] + SAMPLE_CHOICES)
# def test_invalid_choice_model(self):
# s = ChoiceFieldModelSerializer(data={'choice': 'wrong_value'})
# self.assertFalse(s.is_valid())
# self.assertEqual(s.errors, {'choice': ['Select a valid choice. wrong_value is not one of the available choices.']})
# self.assertEqual(s.data['choice'], '')
# def test_empty_choice_model(self):
# """
# Test that the 'empty' value is correctly passed and used depending on
# the 'null' property on the model field.
# """
# s = ChoiceFieldModelSerializer(data={'choice': ''})
# self.assertTrue(s.is_valid())
# self.assertEqual(s.data['choice'], '')
# s = ChoiceFieldModelWithNullSerializer(data={'choice': ''})
# self.assertTrue(s.is_valid())
# self.assertEqual(s.data['choice'], None)
# def test_from_native_empty(self):
# """
# Make sure from_native() returns an empty string on empty param by default.
# """
# f = serializers.ChoiceField(choices=SAMPLE_CHOICES)
# self.assertEqual(f.from_native(''), '')
# self.assertEqual(f.from_native(None), '')
# def test_from_native_empty_override(self):
# """
# Make sure you can override from_native() behavior regarding empty values.
# """
# f = serializers.ChoiceField(choices=SAMPLE_CHOICES, empty=None)
# self.assertEqual(f.from_native(''), None)
# self.assertEqual(f.from_native(None), None)
# def test_metadata_choices(self):
# """
# Make sure proper choices are included in the field's metadata.
# """
# choices = [{'value': v, 'display_name': n} for v, n in SAMPLE_CHOICES]
# f = serializers.ChoiceField(choices=SAMPLE_CHOICES)
# self.assertEqual(f.metadata()['choices'], choices)
# def test_metadata_choices_not_required(self):
# """
# Make sure proper choices are included in the field's metadata.
# """
# choices = [{'value': v, 'display_name': n}
# for v, n in models.fields.BLANK_CHOICE_DASH + SAMPLE_CHOICES]
# f = serializers.ChoiceField(required=False, choices=SAMPLE_CHOICES)
# self.assertEqual(f.metadata()['choices'], choices)
# class EmailFieldTests(TestCase):
# """
# Tests for EmailField attribute values
# """
# class EmailFieldModel(RESTFrameworkModel):
# email_field = models.EmailField(blank=True)
# class EmailFieldWithGivenMaxLengthModel(RESTFrameworkModel):
# email_field = models.EmailField(max_length=150, blank=True)
# def test_default_model_value(self):
# class EmailFieldSerializer(serializers.ModelSerializer):
# class Meta:
# model = self.EmailFieldModel
# serializer = EmailFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['email_field'], 'max_length'), 75)
# def test_given_model_value(self):
# class EmailFieldSerializer(serializers.ModelSerializer):
# class Meta:
# model = self.EmailFieldWithGivenMaxLengthModel
# serializer = EmailFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['email_field'], 'max_length'), 150)
# def test_given_serializer_value(self):
# class EmailFieldSerializer(serializers.ModelSerializer):
# email_field = serializers.EmailField(source='email_field', max_length=20, required=False)
# class Meta:
# model = self.EmailFieldModel
# serializer = EmailFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['email_field'], 'max_length'), 20)
# class SlugFieldTests(TestCase):
# """
# Tests for SlugField attribute values
# """
# class SlugFieldModel(RESTFrameworkModel):
# slug_field = models.SlugField(blank=True)
# class SlugFieldWithGivenMaxLengthModel(RESTFrameworkModel):
# slug_field = models.SlugField(max_length=84, blank=True)
# def test_default_model_value(self):
# class SlugFieldSerializer(serializers.ModelSerializer):
# class Meta:
# model = self.SlugFieldModel
# serializer = SlugFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['slug_field'], 'max_length'), 50)
# def test_given_model_value(self):
# class SlugFieldSerializer(serializers.ModelSerializer):
# class Meta:
# model = self.SlugFieldWithGivenMaxLengthModel
# serializer = SlugFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['slug_field'], 'max_length'), 84)
# def test_given_serializer_value(self):
# class SlugFieldSerializer(serializers.ModelSerializer):
# slug_field = serializers.SlugField(source='slug_field',
# max_length=20, required=False)
# class Meta:
# model = self.SlugFieldModel
# serializer = SlugFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['slug_field'],
# 'max_length'), 20)
# def test_invalid_slug(self):
# """
# Make sure an invalid slug raises ValidationError
# """
# class SlugFieldSerializer(serializers.ModelSerializer):
# slug_field = serializers.SlugField(source='slug_field', max_length=20, required=True)
class Meta:
model = self.SlugFieldModel
# class Meta:
# model = self.SlugFieldModel
s = SlugFieldSerializer(data={'slug_field': 'a b'})
# s = SlugFieldSerializer(data={'slug_field': 'a b'})
self.assertEqual(s.is_valid(), False)
self.assertEqual(s.errors, {'slug_field': ["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]})
# self.assertEqual(s.is_valid(), False)
# self.assertEqual(s.errors, {'slug_field': ["Enter a valid 'slug' consisting of letters, numbers, underscores or hyphens."]})
class URLFieldTests(TestCase):
"""
Tests for URLField attribute values.
# class URLFieldTests(TestCase):
# """
# Tests for URLField attribute values.
(Includes test for #1210, checking that validators can be overridden.)
"""
# (Includes test for #1210, checking that validators can be overridden.)
# """
class URLFieldModel(RESTFrameworkModel):
url_field = models.URLField(blank=True)
# class URLFieldModel(RESTFrameworkModel):
# url_field = models.URLField(blank=True)
class URLFieldWithGivenMaxLengthModel(RESTFrameworkModel):
url_field = models.URLField(max_length=128, blank=True)
# class URLFieldWithGivenMaxLengthModel(RESTFrameworkModel):
# url_field = models.URLField(max_length=128, blank=True)
def test_default_model_value(self):
class URLFieldSerializer(serializers.ModelSerializer):
class Meta:
model = self.URLFieldModel
# def test_default_model_value(self):
# class URLFieldSerializer(serializers.ModelSerializer):
# class Meta:
# model = self.URLFieldModel
serializer = URLFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['url_field'],
'max_length'), 200)
# serializer = URLFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['url_field'],
# 'max_length'), 200)
def test_given_model_value(self):
class URLFieldSerializer(serializers.ModelSerializer):
class Meta:
model = self.URLFieldWithGivenMaxLengthModel
# def test_given_model_value(self):
# class URLFieldSerializer(serializers.ModelSerializer):
# class Meta:
# model = self.URLFieldWithGivenMaxLengthModel
serializer = URLFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['url_field'],
'max_length'), 128)
# serializer = URLFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['url_field'],
# 'max_length'), 128)
def test_given_serializer_value(self):
class URLFieldSerializer(serializers.ModelSerializer):
url_field = serializers.URLField(source='url_field',
max_length=20, required=False)
# def test_given_serializer_value(self):
# class URLFieldSerializer(serializers.ModelSerializer):
# url_field = serializers.URLField(source='url_field',
# max_length=20, required=False)
class Meta:
model = self.URLFieldWithGivenMaxLengthModel
# class Meta:
# model = self.URLFieldWithGivenMaxLengthModel
serializer = URLFieldSerializer(data={})
self.assertEqual(serializer.is_valid(), True)
self.assertEqual(getattr(serializer.fields['url_field'],
'max_length'), 20)
# serializer = URLFieldSerializer(data={})
# self.assertEqual(serializer.is_valid(), True)
# self.assertEqual(getattr(serializer.fields['url_field'],
# 'max_length'), 20)
def test_validators_can_be_overridden(self):
url_field = serializers.URLField(validators=[])
validators = url_field.validators
self.assertEqual([], validators, 'Passing `validators` kwarg should have overridden default validators')
# def test_validators_can_be_overridden(self):
# url_field = serializers.URLField(validators=[])
# validators = url_field.validators
# self.assertEqual([], validators, 'Passing `validators` kwarg should have overridden default validators')
class FieldMetadata(TestCase):
def setUp(self):
self.required_field = serializers.Field()
self.required_field.label = uuid4().hex
self.required_field.required = True
# class FieldMetadata(TestCase):
# def setUp(self):
# self.required_field = serializers.Field()
# self.required_field.label = uuid4().hex
# self.required_field.required = True
self.optional_field = serializers.Field()
self.optional_field.label = uuid4().hex
self.optional_field.required = False
# self.optional_field = serializers.Field()
# self.optional_field.label = uuid4().hex
# self.optional_field.required = False
def test_required(self):
self.assertEqual(self.required_field.metadata()['required'], True)
# def test_required(self):
# self.assertEqual(self.required_field.metadata()['required'], True)
def test_optional(self):
self.assertEqual(self.optional_field.metadata()['required'], False)
# def test_optional(self):
# self.assertEqual(self.optional_field.metadata()['required'], False)
def test_label(self):
for field in (self.required_field, self.optional_field):
self.assertEqual(field.metadata()['label'], field.label)
# def test_label(self):
# for field in (self.required_field, self.optional_field):
# self.assertEqual(field.metadata()['label'], field.label)
class FieldCallableDefault(TestCase):
def setUp(self):
self.simple_callable = lambda: 'foo bar'
# class FieldCallableDefault(TestCase):
# def setUp(self):
# self.simple_callable = lambda: 'foo bar'
def test_default_can_be_simple_callable(self):
"""
Ensure that the 'default' argument can also be a simple callable.
"""
field = serializers.WritableField(default=self.simple_callable)
into = {}
field.field_from_native({}, {}, 'field', into)
self.assertEqual(into, {'field': 'foo bar'})
# def test_default_can_be_simple_callable(self):
# """
# Ensure that the 'default' argument can also be a simple callable.
# """
# field = serializers.WritableField(default=self.simple_callable)
# into = {}
# field.field_from_native({}, {}, 'field', into)
# self.assertEqual(into, {'field': 'foo bar'})
class CustomIntegerField(TestCase):
"""
Test that custom fields apply min_value and max_value constraints
"""
def test_custom_fields_can_be_validated_for_value(self):
# class CustomIntegerField(TestCase):
# """
# Test that custom fields apply min_value and max_value constraints
# """
# def test_custom_fields_can_be_validated_for_value(self):
class MoneyField(models.PositiveIntegerField):
pass
# class MoneyField(models.PositiveIntegerField):
# pass
class EntryModel(models.Model):
bank = MoneyField(validators=[validators.MaxValueValidator(100)])
# class EntryModel(models.Model):
# bank = MoneyField(validators=[validators.MaxValueValidator(100)])
class EntrySerializer(serializers.ModelSerializer):
class Meta:
model = EntryModel
# class EntrySerializer(serializers.ModelSerializer):
# class Meta:
# model = EntryModel
entry = EntryModel(bank=1)
# entry = EntryModel(bank=1)
serializer = EntrySerializer(entry, data={"bank": 11})
self.assertTrue(serializer.is_valid())
# serializer = EntrySerializer(entry, data={"bank": 11})
# self.assertTrue(serializer.is_valid())
serializer = EntrySerializer(entry, data={"bank": -1})
self.assertFalse(serializer.is_valid())
# serializer = EntrySerializer(entry, data={"bank": -1})
# self.assertFalse(serializer.is_valid())
serializer = EntrySerializer(entry, data={"bank": 101})
self.assertFalse(serializer.is_valid())
# serializer = EntrySerializer(entry, data={"bank": 101})
# self.assertFalse(serializer.is_valid())
class BooleanField(TestCase):
"""
Tests for BooleanField
"""
def test_boolean_required(self):
class BooleanRequiredSerializer(serializers.Serializer):
bool_field = serializers.BooleanField(required=True)
# class BooleanField(TestCase):
# """
# Tests for BooleanField
# """
# def test_boolean_required(self):
# class BooleanRequiredSerializer(serializers.Serializer):
# bool_field = serializers.BooleanField(required=True)
self.assertFalse(BooleanRequiredSerializer(data={}).is_valid())
# self.assertFalse(BooleanRequiredSerializer(data={}).is_valid())
class SerializerMethodFieldTest(TestCase):
"""
Tests for the SerializerMethodField field_to_native() behavior
"""
class SerializerTest(serializers.Serializer):
def get_my_test(self, obj):
return obj.my_test[0:5]
# class SerializerMethodFieldTest(TestCase):
# """
# Tests for the SerializerMethodField field_to_native() behavior
# """
# class SerializerTest(serializers.Serializer):
# def get_my_test(self, obj):
# return obj.my_test[0:5]
class Example():
my_test = 'Hey, this is a test !'
# class Example():
# my_test = 'Hey, this is a test !'
def test_field_to_native(self):
s = serializers.SerializerMethodField('get_my_test')
s.initialize(self.SerializerTest(), 'name')
result = s.field_to_native(self.Example(), None)
self.assertEqual(result, 'Hey, ')
# def test_field_to_native(self):
# s = serializers.SerializerMethodField('get_my_test')
# s.initialize(self.SerializerTest(), 'name')
# result = s.field_to_native(self.Example(), None)
# self.assertEqual(result, 'Hey, ')
from __future__ import unicode_literals
from django.test import TestCase
from django.utils import six
from rest_framework import serializers
from rest_framework.compat import BytesIO
import datetime
class UploadedFile(object):
def __init__(self, file=None, created=None):
self.file = file
self.created = created or datetime.datetime.now()
class UploadedFileSerializer(serializers.Serializer):
file = serializers.FileField(required=False)
created = serializers.DateTimeField()
def restore_object(self, attrs, instance=None):
if instance:
instance.file = attrs['file']
instance.created = attrs['created']
return instance
return UploadedFile(**attrs)
class FileSerializerTests(TestCase):
def test_create(self):
now = datetime.datetime.now()
file = BytesIO(six.b('stuff'))
file.name = 'stuff.txt'
file.size = len(file.getvalue())
serializer = UploadedFileSerializer(data={'created': now}, files={'file': file})
uploaded_file = UploadedFile(file=file, created=now)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.object.created, uploaded_file.created)
self.assertEqual(serializer.object.file, uploaded_file.file)
self.assertFalse(serializer.object is uploaded_file)
def test_creation_failure(self):
"""
Passing files=None should result in an ValidationError
Regression test for:
https://github.com/tomchristie/django-rest-framework/issues/542
"""
now = datetime.datetime.now()
serializer = UploadedFileSerializer(data={'created': now})
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.object.created, now)
self.assertIsNone(serializer.object.file)
def test_remove_with_empty_string(self):
"""
Passing empty string as data should cause file to be removed
Test for:
https://github.com/tomchristie/django-rest-framework/issues/937
"""
now = datetime.datetime.now()
file = BytesIO(six.b('stuff'))
file.name = 'stuff.txt'
file.size = len(file.getvalue())
uploaded_file = UploadedFile(file=file, created=now)
serializer = UploadedFileSerializer(instance=uploaded_file, data={'created': now, 'file': ''})
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.object.created, uploaded_file.created)
self.assertIsNone(serializer.object.file)
def test_validation_error_with_non_file(self):
"""
Passing non-files should raise a validation error.
"""
now = datetime.datetime.now()
errmsg = 'No file was submitted. Check the encoding type on the form.'
serializer = UploadedFileSerializer(data={'created': now, 'file': 'abc'})
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'file': [errmsg]})
def test_validation_with_no_data(self):
"""
Validation should still function when no data dictionary is provided.
"""
uploaded_file = BytesIO(six.b('stuff'))
uploaded_file.name = 'stuff.txt'
uploaded_file.size = len(uploaded_file.getvalue())
serializer = UploadedFileSerializer(files={'file': uploaded_file})
self.assertFalse(serializer.is_valid())
# from __future__ import unicode_literals
# from django.test import TestCase
# from django.utils import six
# from rest_framework import serializers
# from rest_framework.compat import BytesIO
# import datetime
# class UploadedFile(object):
# def __init__(self, file=None, created=None):
# self.file = file
# self.created = created or datetime.datetime.now()
# class UploadedFileSerializer(serializers.Serializer):
# file = serializers.FileField(required=False)
# created = serializers.DateTimeField()
# def restore_object(self, attrs, instance=None):
# if instance:
# instance.file = attrs['file']
# instance.created = attrs['created']
# return instance
# return UploadedFile(**attrs)
# class FileSerializerTests(TestCase):
# def test_create(self):
# now = datetime.datetime.now()
# file = BytesIO(six.b('stuff'))
# file.name = 'stuff.txt'
# file.size = len(file.getvalue())
# serializer = UploadedFileSerializer(data={'created': now}, files={'file': file})
# uploaded_file = UploadedFile(file=file, created=now)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.object.created, uploaded_file.created)
# self.assertEqual(serializer.object.file, uploaded_file.file)
# self.assertFalse(serializer.object is uploaded_file)
# def test_creation_failure(self):
# """
# Passing files=None should result in an ValidationError
# Regression test for:
# https://github.com/tomchristie/django-rest-framework/issues/542
# """
# now = datetime.datetime.now()
# serializer = UploadedFileSerializer(data={'created': now})
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.object.created, now)
# self.assertIsNone(serializer.object.file)
# def test_remove_with_empty_string(self):
# """
# Passing empty string as data should cause file to be removed
# Test for:
# https://github.com/tomchristie/django-rest-framework/issues/937
# """
# now = datetime.datetime.now()
# file = BytesIO(six.b('stuff'))
# file.name = 'stuff.txt'
# file.size = len(file.getvalue())
# uploaded_file = UploadedFile(file=file, created=now)
# serializer = UploadedFileSerializer(instance=uploaded_file, data={'created': now, 'file': ''})
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.object.created, uploaded_file.created)
# self.assertIsNone(serializer.object.file)
# def test_validation_error_with_non_file(self):
# """
# Passing non-files should raise a validation error.
# """
# now = datetime.datetime.now()
# errmsg = 'No file was submitted. Check the encoding type on the form.'
# serializer = UploadedFileSerializer(data={'created': now, 'file': 'abc'})
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'file': [errmsg]})
# def test_validation_with_no_data(self):
# """
# Validation should still function when no data dictionary is provided.
# """
# uploaded_file = BytesIO(six.b('stuff'))
# uploaded_file.name = 'stuff.txt'
# uploaded_file.size = len(uploaded_file.getvalue())
# serializer = UploadedFileSerializer(files={'file': uploaded_file})
# self.assertFalse(serializer.is_valid())
from __future__ import unicode_literals
from django.contrib.contenttypes.models import ContentType
from django.contrib.contenttypes.generic import GenericRelation, GenericForeignKey
from django.db import models
from django.test import TestCase
from rest_framework import serializers
from rest_framework.compat import python_2_unicode_compatible
@python_2_unicode_compatible
class Tag(models.Model):
"""
Tags have a descriptive slug, and are attached to an arbitrary object.
"""
tag = models.SlugField()
content_type = models.ForeignKey(ContentType)
object_id = models.PositiveIntegerField()
tagged_item = GenericForeignKey('content_type', 'object_id')
def __str__(self):
return self.tag
@python_2_unicode_compatible
class Bookmark(models.Model):
"""
A URL bookmark that may have multiple tags attached.
"""
url = models.URLField()
tags = GenericRelation(Tag)
def __str__(self):
return 'Bookmark: %s' % self.url
@python_2_unicode_compatible
class Note(models.Model):
"""
A textual note that may have multiple tags attached.
"""
text = models.TextField()
tags = GenericRelation(Tag)
def __str__(self):
return 'Note: %s' % self.text
class TestGenericRelations(TestCase):
def setUp(self):
self.bookmark = Bookmark.objects.create(url='https://www.djangoproject.com/')
Tag.objects.create(tagged_item=self.bookmark, tag='django')
Tag.objects.create(tagged_item=self.bookmark, tag='python')
self.note = Note.objects.create(text='Remember the milk')
Tag.objects.create(tagged_item=self.note, tag='reminder')
def test_generic_relation(self):
"""
Test a relationship that spans a GenericRelation field.
IE. A reverse generic relationship.
"""
class BookmarkSerializer(serializers.ModelSerializer):
tags = serializers.RelatedField(many=True)
class Meta:
model = Bookmark
exclude = ('id',)
serializer = BookmarkSerializer(self.bookmark)
expected = {
'tags': ['django', 'python'],
'url': 'https://www.djangoproject.com/'
}
self.assertEqual(serializer.data, expected)
def test_generic_nested_relation(self):
"""
Test saving a GenericRelation field via a nested serializer.
"""
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
exclude = ('content_type', 'object_id')
class BookmarkSerializer(serializers.ModelSerializer):
tags = TagSerializer(many=True)
class Meta:
model = Bookmark
exclude = ('id',)
data = {
'url': 'https://docs.djangoproject.com/',
'tags': [
{'tag': 'contenttypes'},
{'tag': 'genericrelations'},
]
}
serializer = BookmarkSerializer(data=data)
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.object.tags.count(), 2)
def test_generic_fk(self):
"""
Test a relationship that spans a GenericForeignKey field.
IE. A forward generic relationship.
"""
class TagSerializer(serializers.ModelSerializer):
tagged_item = serializers.RelatedField()
class Meta:
model = Tag
exclude = ('id', 'content_type', 'object_id')
serializer = TagSerializer(Tag.objects.all(), many=True)
expected = [
{
'tag': 'django',
'tagged_item': 'Bookmark: https://www.djangoproject.com/'
},
{
'tag': 'python',
'tagged_item': 'Bookmark: https://www.djangoproject.com/'
},
{
'tag': 'reminder',
'tagged_item': 'Note: Remember the milk'
}
]
self.assertEqual(serializer.data, expected)
def test_restore_object_generic_fk(self):
"""
Ensure an object with a generic foreign key can be restored.
"""
class TagSerializer(serializers.ModelSerializer):
class Meta:
model = Tag
exclude = ('content_type', 'object_id')
serializer = TagSerializer()
bookmark = Bookmark(url='http://example.com')
attrs = {'tagged_item': bookmark, 'tag': 'example'}
tag = serializer.restore_object(attrs)
self.assertEqual(tag.tagged_item, bookmark)
# from __future__ import unicode_literals
# from django.contrib.contenttypes.models import ContentType
# from django.contrib.contenttypes.generic import GenericRelation, GenericForeignKey
# from django.db import models
# from django.test import TestCase
# from rest_framework import serializers
# from rest_framework.compat import python_2_unicode_compatible
# @python_2_unicode_compatible
# class Tag(models.Model):
# """
# Tags have a descriptive slug, and are attached to an arbitrary object.
# """
# tag = models.SlugField()
# content_type = models.ForeignKey(ContentType)
# object_id = models.PositiveIntegerField()
# tagged_item = GenericForeignKey('content_type', 'object_id')
# def __str__(self):
# return self.tag
# @python_2_unicode_compatible
# class Bookmark(models.Model):
# """
# A URL bookmark that may have multiple tags attached.
# """
# url = models.URLField()
# tags = GenericRelation(Tag)
# def __str__(self):
# return 'Bookmark: %s' % self.url
# @python_2_unicode_compatible
# class Note(models.Model):
# """
# A textual note that may have multiple tags attached.
# """
# text = models.TextField()
# tags = GenericRelation(Tag)
# def __str__(self):
# return 'Note: %s' % self.text
# class TestGenericRelations(TestCase):
# def setUp(self):
# self.bookmark = Bookmark.objects.create(url='https://www.djangoproject.com/')
# Tag.objects.create(tagged_item=self.bookmark, tag='django')
# Tag.objects.create(tagged_item=self.bookmark, tag='python')
# self.note = Note.objects.create(text='Remember the milk')
# Tag.objects.create(tagged_item=self.note, tag='reminder')
# def test_generic_relation(self):
# """
# Test a relationship that spans a GenericRelation field.
# IE. A reverse generic relationship.
# """
# class BookmarkSerializer(serializers.ModelSerializer):
# tags = serializers.RelatedField(many=True)
# class Meta:
# model = Bookmark
# exclude = ('id',)
# serializer = BookmarkSerializer(self.bookmark)
# expected = {
# 'tags': ['django', 'python'],
# 'url': 'https://www.djangoproject.com/'
# }
# self.assertEqual(serializer.data, expected)
# def test_generic_nested_relation(self):
# """
# Test saving a GenericRelation field via a nested serializer.
# """
# class TagSerializer(serializers.ModelSerializer):
# class Meta:
# model = Tag
# exclude = ('content_type', 'object_id')
# class BookmarkSerializer(serializers.ModelSerializer):
# tags = TagSerializer(many=True)
# class Meta:
# model = Bookmark
# exclude = ('id',)
# data = {
# 'url': 'https://docs.djangoproject.com/',
# 'tags': [
# {'tag': 'contenttypes'},
# {'tag': 'genericrelations'},
# ]
# }
# serializer = BookmarkSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# serializer.save()
# self.assertEqual(serializer.object.tags.count(), 2)
# def test_generic_fk(self):
# """
# Test a relationship that spans a GenericForeignKey field.
# IE. A forward generic relationship.
# """
# class TagSerializer(serializers.ModelSerializer):
# tagged_item = serializers.RelatedField()
# class Meta:
# model = Tag
# exclude = ('id', 'content_type', 'object_id')
# serializer = TagSerializer(Tag.objects.all(), many=True)
# expected = [
# {
# 'tag': 'django',
# 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
# },
# {
# 'tag': 'python',
# 'tagged_item': 'Bookmark: https://www.djangoproject.com/'
# },
# {
# 'tag': 'reminder',
# 'tagged_item': 'Note: Remember the milk'
# }
# ]
# self.assertEqual(serializer.data, expected)
# def test_restore_object_generic_fk(self):
# """
# Ensure an object with a generic foreign key can be restored.
# """
# class TagSerializer(serializers.ModelSerializer):
# class Meta:
# model = Tag
# exclude = ('content_type', 'object_id')
# serializer = TagSerializer()
# bookmark = Bookmark(url='http://example.com')
# attrs = {'tagged_item': bookmark, 'tag': 'example'}
# tag = serializer.restore_object(attrs)
# self.assertEqual(tag.tagged_item, bookmark)
......@@ -33,13 +33,9 @@ class InstanceView(generics.RetrieveUpdateDestroyAPIView):
"""
Example description for OPTIONS.
"""
queryset = BasicModel.objects.all()
queryset = BasicModel.objects.exclude(text='filtered out')
serializer_class = BasicSerializer
def get_queryset(self):
queryset = super(InstanceView, self).get_queryset()
return queryset.exclude(text='filtered out')
class FKInstanceView(generics.RetrieveUpdateDestroyAPIView):
"""
......@@ -50,11 +46,11 @@ class FKInstanceView(generics.RetrieveUpdateDestroyAPIView):
class SlugSerializer(serializers.ModelSerializer):
slug = serializers.Field() # read only
slug = serializers.Field(read_only=True)
class Meta:
model = SlugBasedModel
exclude = ('id',)
fields = ('text', 'slug')
class SlugBasedInstanceView(InstanceView):
......@@ -125,46 +121,46 @@ class TestRootView(TestCase):
self.assertEqual(response.status_code, status.HTTP_405_METHOD_NOT_ALLOWED)
self.assertEqual(response.data, {"detail": "Method 'DELETE' not allowed."})
def test_options_root_view(self):
"""
OPTIONS requests to ListCreateAPIView should return metadata
"""
request = factory.options('/')
with self.assertNumQueries(0):
response = self.view(request).render()
expected = {
'parses': [
'application/json',
'application/x-www-form-urlencoded',
'multipart/form-data'
],
'renders': [
'application/json',
'text/html'
],
'name': 'Root',
'description': 'Example description for OPTIONS.',
'actions': {
'POST': {
'text': {
'max_length': 100,
'read_only': False,
'required': True,
'type': 'string',
"label": "Text comes here",
"help_text": "Text description."
},
'id': {
'read_only': True,
'required': False,
'type': 'integer',
'label': 'ID',
},
}
}
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, expected)
# def test_options_root_view(self):
# """
# OPTIONS requests to ListCreateAPIView should return metadata
# """
# request = factory.options('/')
# with self.assertNumQueries(0):
# response = self.view(request).render()
# expected = {
# 'parses': [
# 'application/json',
# 'application/x-www-form-urlencoded',
# 'multipart/form-data'
# ],
# 'renders': [
# 'application/json',
# 'text/html'
# ],
# 'name': 'Root',
# 'description': 'Example description for OPTIONS.',
# 'actions': {
# 'POST': {
# 'text': {
# 'max_length': 100,
# 'read_only': False,
# 'required': True,
# 'type': 'string',
# "label": "Text comes here",
# "help_text": "Text description."
# },
# 'id': {
# 'read_only': True,
# 'required': False,
# 'type': 'integer',
# 'label': 'ID',
# },
# }
# }
# }
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, expected)
def test_post_cannot_set_id(self):
"""
......@@ -223,10 +219,10 @@ class TestInstanceView(TestCase):
"""
data = {'text': 'foobar'}
request = factory.put('/1', data, format='json')
with self.assertNumQueries(2):
with self.assertNumQueries(3):
response = self.view(request, pk='1').render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
self.assertEqual(dict(response.data), {'id': 1, 'text': 'foobar'})
updated = self.objects.get(id=1)
self.assertEqual(updated.text, 'foobar')
......@@ -237,7 +233,7 @@ class TestInstanceView(TestCase):
data = {'text': 'foobar'}
request = factory.patch('/1', data, format='json')
with self.assertNumQueries(2):
with self.assertNumQueries(3):
response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
......@@ -256,88 +252,88 @@ class TestInstanceView(TestCase):
ids = [obj.id for obj in self.objects.all()]
self.assertEqual(ids, [2, 3])
def test_options_instance_view(self):
"""
OPTIONS requests to RetrieveUpdateDestroyAPIView should return metadata
"""
request = factory.options('/1')
with self.assertNumQueries(1):
response = self.view(request, pk=1).render()
expected = {
'parses': [
'application/json',
'application/x-www-form-urlencoded',
'multipart/form-data'
],
'renders': [
'application/json',
'text/html'
],
'name': 'Instance',
'description': 'Example description for OPTIONS.',
'actions': {
'PUT': {
'text': {
'max_length': 100,
'read_only': False,
'required': True,
'type': 'string',
'label': 'Text comes here',
'help_text': 'Text description.'
},
'id': {
'read_only': True,
'required': False,
'type': 'integer',
'label': 'ID',
},
}
}
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, expected)
def test_options_before_instance_create(self):
"""
OPTIONS requests to RetrieveUpdateDestroyAPIView should return metadata
before the instance has been created
"""
request = factory.options('/999')
with self.assertNumQueries(1):
response = self.view(request, pk=999).render()
expected = {
'parses': [
'application/json',
'application/x-www-form-urlencoded',
'multipart/form-data'
],
'renders': [
'application/json',
'text/html'
],
'name': 'Instance',
'description': 'Example description for OPTIONS.',
'actions': {
'PUT': {
'text': {
'max_length': 100,
'read_only': False,
'required': True,
'type': 'string',
'label': 'Text comes here',
'help_text': 'Text description.'
},
'id': {
'read_only': True,
'required': False,
'type': 'integer',
'label': 'ID',
},
}
}
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, expected)
# def test_options_instance_view(self):
# """
# OPTIONS requests to RetrieveUpdateDestroyAPIView should return metadata
# """
# request = factory.options('/1')
# with self.assertNumQueries(1):
# response = self.view(request, pk=1).render()
# expected = {
# 'parses': [
# 'application/json',
# 'application/x-www-form-urlencoded',
# 'multipart/form-data'
# ],
# 'renders': [
# 'application/json',
# 'text/html'
# ],
# 'name': 'Instance',
# 'description': 'Example description for OPTIONS.',
# 'actions': {
# 'PUT': {
# 'text': {
# 'max_length': 100,
# 'read_only': False,
# 'required': True,
# 'type': 'string',
# 'label': 'Text comes here',
# 'help_text': 'Text description.'
# },
# 'id': {
# 'read_only': True,
# 'required': False,
# 'type': 'integer',
# 'label': 'ID',
# },
# }
# }
# }
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, expected)
# def test_options_before_instance_create(self):
# """
# OPTIONS requests to RetrieveUpdateDestroyAPIView should return metadata
# before the instance has been created
# """
# request = factory.options('/999')
# with self.assertNumQueries(1):
# response = self.view(request, pk=999).render()
# expected = {
# 'parses': [
# 'application/json',
# 'application/x-www-form-urlencoded',
# 'multipart/form-data'
# ],
# 'renders': [
# 'application/json',
# 'text/html'
# ],
# 'name': 'Instance',
# 'description': 'Example description for OPTIONS.',
# 'actions': {
# 'PUT': {
# 'text': {
# 'max_length': 100,
# 'read_only': False,
# 'required': True,
# 'type': 'string',
# 'label': 'Text comes here',
# 'help_text': 'Text description.'
# },
# 'id': {
# 'read_only': True,
# 'required': False,
# 'type': 'integer',
# 'label': 'ID',
# },
# }
# }
# }
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, expected)
def test_get_instance_view_incorrect_arg(self):
"""
......@@ -355,7 +351,7 @@ class TestInstanceView(TestCase):
"""
data = {'id': 999, 'text': 'foobar'}
request = factory.put('/1', data, format='json')
with self.assertNumQueries(2):
with self.assertNumQueries(3):
response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
......@@ -370,7 +366,7 @@ class TestInstanceView(TestCase):
self.objects.get(id=1).delete()
data = {'text': 'foobar'}
request = factory.put('/1', data, format='json')
with self.assertNumQueries(3):
with self.assertNumQueries(2):
response = self.view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response.data, {'id': 1, 'text': 'foobar'})
......@@ -396,7 +392,7 @@ class TestInstanceView(TestCase):
data = {'text': 'foobar'}
# pk fields can not be created on demand, only the database can set the pk for a new object
request = factory.put('/5', data, format='json')
with self.assertNumQueries(3):
with self.assertNumQueries(2):
response = self.view(request, pk=5).render()
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
new_obj = self.objects.get(pk=5)
......@@ -446,52 +442,52 @@ class TestFKInstanceView(TestCase):
]
self.view = FKInstanceView.as_view()
def test_options_root_view(self):
"""
OPTIONS requests to ListCreateAPIView should return metadata
"""
request = factory.options('/999')
with self.assertNumQueries(1):
response = self.view(request, pk=999).render()
expected = {
'name': 'Fk Instance',
'description': 'FK: example description for OPTIONS.',
'renders': [
'application/json',
'text/html'
],
'parses': [
'application/json',
'application/x-www-form-urlencoded',
'multipart/form-data'
],
'actions': {
'PUT': {
'id': {
'type': 'integer',
'required': False,
'read_only': True,
'label': 'ID'
},
'name': {
'type': 'string',
'required': True,
'read_only': False,
'label': 'name',
'max_length': 100
},
'target': {
'type': 'field',
'required': True,
'read_only': False,
'label': 'Target',
'help_text': 'Target'
}
}
}
}
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, expected)
# def test_options_root_view(self):
# """
# OPTIONS requests to ListCreateAPIView should return metadata
# """
# request = factory.options('/999')
# with self.assertNumQueries(1):
# response = self.view(request, pk=999).render()
# expected = {
# 'name': 'Fk Instance',
# 'description': 'FK: example description for OPTIONS.',
# 'renders': [
# 'application/json',
# 'text/html'
# ],
# 'parses': [
# 'application/json',
# 'application/x-www-form-urlencoded',
# 'multipart/form-data'
# ],
# 'actions': {
# 'PUT': {
# 'id': {
# 'type': 'integer',
# 'required': False,
# 'read_only': True,
# 'label': 'ID'
# },
# 'name': {
# 'type': 'string',
# 'required': True,
# 'read_only': False,
# 'label': 'name',
# 'max_length': 100
# },
# 'target': {
# 'type': 'field',
# 'required': True,
# 'read_only': False,
# 'label': 'Target',
# 'help_text': 'Target'
# }
# }
# }
# }
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, expected)
class TestOverriddenGetObject(TestCase):
......
from __future__ import unicode_literals
import json
from django.test import TestCase
from rest_framework import generics, status, serializers
from django.conf.urls import patterns, url
from rest_framework.settings import api_settings
from rest_framework.test import APIRequestFactory
from tests.models import (
Anchor, BasicModel, ManyToManyModel, BlogPost, BlogPostComment,
Album, Photo, OptionalRelationModel
)
# from __future__ import unicode_literals
# import json
# from django.test import TestCase
# from rest_framework import generics, status, serializers
# from django.conf.urls import patterns, url
# from rest_framework.settings import api_settings
# from rest_framework.test import APIRequestFactory
# from tests.models import (
# Anchor, BasicModel, ManyToManyModel, BlogPost, BlogPostComment,
# Album, Photo, OptionalRelationModel
# )
factory = APIRequestFactory()
# factory = APIRequestFactory()
class BlogPostCommentSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='blogpostcomment-detail')
text = serializers.CharField()
blog_post_url = serializers.HyperlinkedRelatedField(source='blog_post', view_name='blogpost-detail')
# class BlogPostCommentSerializer(serializers.ModelSerializer):
# url = serializers.HyperlinkedIdentityField(view_name='blogpostcomment-detail')
# text = serializers.CharField()
# blog_post_url = serializers.HyperlinkedRelatedField(source='blog_post', view_name='blogpost-detail')
class Meta:
model = BlogPostComment
fields = ('text', 'blog_post_url', 'url')
# class Meta:
# model = BlogPostComment
# fields = ('text', 'blog_post_url', 'url')
class PhotoSerializer(serializers.Serializer):
description = serializers.CharField()
album_url = serializers.HyperlinkedRelatedField(source='album', view_name='album-detail', queryset=Album.objects.all(), lookup_field='title')
# class PhotoSerializer(serializers.Serializer):
# description = serializers.CharField()
# album_url = serializers.HyperlinkedRelatedField(source='album', view_name='album-detail', queryset=Album.objects.all(), lookup_field='title')
def restore_object(self, attrs, instance=None):
return Photo(**attrs)
# def restore_object(self, attrs, instance=None):
# return Photo(**attrs)
class AlbumSerializer(serializers.ModelSerializer):
url = serializers.HyperlinkedIdentityField(view_name='album-detail', lookup_field='title')
# class AlbumSerializer(serializers.ModelSerializer):
# url = serializers.HyperlinkedIdentityField(view_name='album-detail', lookup_field='title')
class Meta:
model = Album
fields = ('title', 'url')
# class Meta:
# model = Album
# fields = ('title', 'url')
class BasicSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = BasicModel
# class BasicSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = BasicModel
class AnchorSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = Anchor
# class AnchorSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = Anchor
class ManyToManySerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ManyToManyModel
# class ManyToManySerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = ManyToManyModel
class BlogPostSerializer(serializers.ModelSerializer):
class Meta:
model = BlogPost
# class BlogPostSerializer(serializers.ModelSerializer):
# class Meta:
# model = BlogPost
class OptionalRelationSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = OptionalRelationModel
# class OptionalRelationSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = OptionalRelationModel
class BasicList(generics.ListCreateAPIView):
queryset = BasicModel.objects.all()
serializer_class = BasicSerializer
# class BasicList(generics.ListCreateAPIView):
# queryset = BasicModel.objects.all()
# serializer_class = BasicSerializer
class BasicDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = BasicModel.objects.all()
serializer_class = BasicSerializer
# class BasicDetail(generics.RetrieveUpdateDestroyAPIView):
# queryset = BasicModel.objects.all()
# serializer_class = BasicSerializer
class AnchorDetail(generics.RetrieveAPIView):
queryset = Anchor.objects.all()
serializer_class = AnchorSerializer
# class AnchorDetail(generics.RetrieveAPIView):
# queryset = Anchor.objects.all()
# serializer_class = AnchorSerializer
class ManyToManyList(generics.ListAPIView):
queryset = ManyToManyModel.objects.all()
serializer_class = ManyToManySerializer
# class ManyToManyList(generics.ListAPIView):
# queryset = ManyToManyModel.objects.all()
# serializer_class = ManyToManySerializer
class ManyToManyDetail(generics.RetrieveAPIView):
queryset = ManyToManyModel.objects.all()
serializer_class = ManyToManySerializer
# class ManyToManyDetail(generics.RetrieveAPIView):
# queryset = ManyToManyModel.objects.all()
# serializer_class = ManyToManySerializer
class BlogPostCommentListCreate(generics.ListCreateAPIView):
queryset = BlogPostComment.objects.all()
serializer_class = BlogPostCommentSerializer
# class BlogPostCommentListCreate(generics.ListCreateAPIView):
# queryset = BlogPostComment.objects.all()
# serializer_class = BlogPostCommentSerializer
class BlogPostCommentDetail(generics.RetrieveAPIView):
queryset = BlogPostComment.objects.all()
serializer_class = BlogPostCommentSerializer
# class BlogPostCommentDetail(generics.RetrieveAPIView):
# queryset = BlogPostComment.objects.all()
# serializer_class = BlogPostCommentSerializer
class BlogPostDetail(generics.RetrieveAPIView):
queryset = BlogPost.objects.all()
serializer_class = BlogPostSerializer
# class BlogPostDetail(generics.RetrieveAPIView):
# queryset = BlogPost.objects.all()
# serializer_class = BlogPostSerializer
class PhotoListCreate(generics.ListCreateAPIView):
queryset = Photo.objects.all()
serializer_class = PhotoSerializer
# class PhotoListCreate(generics.ListCreateAPIView):
# queryset = Photo.objects.all()
# serializer_class = PhotoSerializer
class AlbumDetail(generics.RetrieveAPIView):
queryset = Album.objects.all()
serializer_class = AlbumSerializer
lookup_field = 'title'
# class AlbumDetail(generics.RetrieveAPIView):
# queryset = Album.objects.all()
# serializer_class = AlbumSerializer
# lookup_field = 'title'
class OptionalRelationDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = OptionalRelationModel.objects.all()
serializer_class = OptionalRelationSerializer
# class OptionalRelationDetail(generics.RetrieveUpdateDestroyAPIView):
# queryset = OptionalRelationModel.objects.all()
# serializer_class = OptionalRelationSerializer
urlpatterns = patterns(
'',
url(r'^basic/$', BasicList.as_view(), name='basicmodel-list'),
url(r'^basic/(?P<pk>\d+)/$', BasicDetail.as_view(), name='basicmodel-detail'),
url(r'^anchor/(?P<pk>\d+)/$', AnchorDetail.as_view(), name='anchor-detail'),
url(r'^manytomany/$', ManyToManyList.as_view(), name='manytomanymodel-list'),
url(r'^manytomany/(?P<pk>\d+)/$', ManyToManyDetail.as_view(), name='manytomanymodel-detail'),
url(r'^posts/(?P<pk>\d+)/$', BlogPostDetail.as_view(), name='blogpost-detail'),
url(r'^comments/$', BlogPostCommentListCreate.as_view(), name='blogpostcomment-list'),
url(r'^comments/(?P<pk>\d+)/$', BlogPostCommentDetail.as_view(), name='blogpostcomment-detail'),
url(r'^albums/(?P<title>\w[\w-]*)/$', AlbumDetail.as_view(), name='album-detail'),
url(r'^photos/$', PhotoListCreate.as_view(), name='photo-list'),
url(r'^optionalrelation/(?P<pk>\d+)/$', OptionalRelationDetail.as_view(), name='optionalrelationmodel-detail'),
)
class TestBasicHyperlinkedView(TestCase):
urls = 'tests.test_hyperlinkedserializers'
def setUp(self):
"""
Create 3 BasicModel instances.
"""
items = ['foo', 'bar', 'baz']
for item in items:
BasicModel(text=item).save()
self.objects = BasicModel.objects
self.data = [
{'url': 'http://testserver/basic/%d/' % obj.id, 'text': obj.text}
for obj in self.objects.all()
]
self.list_view = BasicList.as_view()
self.detail_view = BasicDetail.as_view()
def test_get_list_view(self):
"""
GET requests to ListCreateAPIView should return list of objects.
"""
request = factory.get('/basic/')
response = self.list_view(request).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, self.data)
def test_get_detail_view(self):
"""
GET requests to ListCreateAPIView should return list of objects.
"""
request = factory.get('/basic/1')
response = self.detail_view(request, pk=1).render()
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, self.data[0])
class TestManyToManyHyperlinkedView(TestCase):
urls = 'tests.test_hyperlinkedserializers'
def setUp(self):
"""
Create 3 BasicModel instances.
"""
items = ['foo', 'bar', 'baz']
anchors = []
for item in items:
anchor = Anchor(text=item)
anchor.save()
anchors.append(anchor)
manytomany = ManyToManyModel()
manytomany.save()
manytomany.rel.add(*anchors)
self.data = [{
'url': 'http://testserver/manytomany/1/',
'rel': [
'http://testserver/anchor/1/',
'http://testserver/anchor/2/',
'http://testserver/anchor/3/',
]
}]
self.list_view = ManyToManyList.as_view()
self.detail_view = ManyToManyDetail.as_view()
def test_get_list_view(self):
"""
GET requests to ListCreateAPIView should return list of objects.
"""
request = factory.get('/manytomany/')
response = self.list_view(request)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, self.data)
def test_get_detail_view(self):
"""
GET requests to ListCreateAPIView should return list of objects.
"""
request = factory.get('/manytomany/1/')
response = self.detail_view(request, pk=1)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, self.data[0])
class TestHyperlinkedIdentityFieldLookup(TestCase):
urls = 'tests.test_hyperlinkedserializers'
def setUp(self):
"""
Create 3 Album instances.
"""
titles = ['foo', 'bar', 'baz']
for title in titles:
album = Album(title=title)
album.save()
self.detail_view = AlbumDetail.as_view()
self.data = {
'foo': {'title': 'foo', 'url': 'http://testserver/albums/foo/'},
'bar': {'title': 'bar', 'url': 'http://testserver/albums/bar/'},
'baz': {'title': 'baz', 'url': 'http://testserver/albums/baz/'}
}
def test_lookup_field(self):
"""
GET requests to AlbumDetail view should return serialized Albums
with a url field keyed by `title`.
"""
for album in Album.objects.all():
request = factory.get('/albums/{0}/'.format(album.title))
response = self.detail_view(request, title=album.title)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, self.data[album.title])
class TestCreateWithForeignKeys(TestCase):
urls = 'tests.test_hyperlinkedserializers'
def setUp(self):
"""
Create a blog post
"""
self.post = BlogPost.objects.create(title="Test post")
self.create_view = BlogPostCommentListCreate.as_view()
def test_create_comment(self):
data = {
'text': 'A test comment',
'blog_post_url': 'http://testserver/posts/1/'
}
request = factory.post('/comments/', data=data)
response = self.create_view(request)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertEqual(response['Location'], 'http://testserver/comments/1/')
self.assertEqual(self.post.blogpostcomment_set.count(), 1)
self.assertEqual(self.post.blogpostcomment_set.all()[0].text, 'A test comment')
class TestCreateWithForeignKeysAndCustomSlug(TestCase):
urls = 'tests.test_hyperlinkedserializers'
def setUp(self):
"""
Create an Album
"""
self.post = Album.objects.create(title='test-album')
self.list_create_view = PhotoListCreate.as_view()
def test_create_photo(self):
data = {
'description': 'A test photo',
'album_url': 'http://testserver/albums/test-album/'
}
request = factory.post('/photos/', data=data)
response = self.list_create_view(request)
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
self.assertNotIn('Location', response, msg='Location should only be included if there is a "url" field on the serializer')
self.assertEqual(self.post.photo_set.count(), 1)
self.assertEqual(self.post.photo_set.all()[0].description, 'A test photo')
class TestOptionalRelationHyperlinkedView(TestCase):
urls = 'tests.test_hyperlinkedserializers'
def setUp(self):
"""
Create 1 OptionalRelationModel instances.
"""
OptionalRelationModel().save()
self.objects = OptionalRelationModel.objects
self.detail_view = OptionalRelationDetail.as_view()
self.data = {"url": "http://testserver/optionalrelation/1/", "other": None}
def test_get_detail_view(self):
"""
GET requests to RetrieveAPIView with optional relations should return None
for non existing relations.
"""
request = factory.get('/optionalrelationmodel-detail/1')
response = self.detail_view(request, pk=1)
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertEqual(response.data, self.data)
def test_put_detail_view(self):
"""
PUT requests to RetrieveUpdateDestroyAPIView with optional relations
should accept None for non existing relations.
"""
response = self.client.put('/optionalrelation/1/',
data=json.dumps(self.data),
content_type='application/json')
self.assertEqual(response.status_code, status.HTTP_200_OK)
class TestOverriddenURLField(TestCase):
def setUp(self):
class OverriddenURLSerializer(serializers.HyperlinkedModelSerializer):
url = serializers.SerializerMethodField('get_url')
class Meta:
model = BlogPost
fields = ('title', 'url')
def get_url(self, obj):
return 'foo bar'
self.Serializer = OverriddenURLSerializer
self.obj = BlogPost.objects.create(title='New blog post')
def test_overridden_url_field(self):
"""
The 'url' field should respect overriding.
Regression test for #936.
"""
serializer = self.Serializer(self.obj)
self.assertEqual(
serializer.data,
{'title': 'New blog post', 'url': 'foo bar'}
)
class TestURLFieldNameBySettings(TestCase):
urls = 'tests.test_hyperlinkedserializers'
def setUp(self):
self.saved_url_field_name = api_settings.URL_FIELD_NAME
api_settings.URL_FIELD_NAME = 'global_url_field'
class Serializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = BlogPost
fields = ('title', api_settings.URL_FIELD_NAME)
self.Serializer = Serializer
self.obj = BlogPost.objects.create(title="New blog post")
def tearDown(self):
api_settings.URL_FIELD_NAME = self.saved_url_field_name
def test_overridden_url_field_name(self):
request = factory.get('/posts/')
serializer = self.Serializer(self.obj, context={'request': request})
self.assertIn(api_settings.URL_FIELD_NAME, serializer.data)
class TestURLFieldNameByOptions(TestCase):
urls = 'tests.test_hyperlinkedserializers'
def setUp(self):
class Serializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = BlogPost
fields = ('title', 'serializer_url_field')
url_field_name = 'serializer_url_field'
self.Serializer = Serializer
self.obj = BlogPost.objects.create(title="New blog post")
def test_overridden_url_field_name(self):
request = factory.get('/posts/')
serializer = self.Serializer(self.obj, context={'request': request})
self.assertIn(self.Serializer.Meta.url_field_name, serializer.data)
# urlpatterns = patterns(
# '',
# url(r'^basic/$', BasicList.as_view(), name='basicmodel-list'),
# url(r'^basic/(?P<pk>\d+)/$', BasicDetail.as_view(), name='basicmodel-detail'),
# url(r'^anchor/(?P<pk>\d+)/$', AnchorDetail.as_view(), name='anchor-detail'),
# url(r'^manytomany/$', ManyToManyList.as_view(), name='manytomanymodel-list'),
# url(r'^manytomany/(?P<pk>\d+)/$', ManyToManyDetail.as_view(), name='manytomanymodel-detail'),
# url(r'^posts/(?P<pk>\d+)/$', BlogPostDetail.as_view(), name='blogpost-detail'),
# url(r'^comments/$', BlogPostCommentListCreate.as_view(), name='blogpostcomment-list'),
# url(r'^comments/(?P<pk>\d+)/$', BlogPostCommentDetail.as_view(), name='blogpostcomment-detail'),
# url(r'^albums/(?P<title>\w[\w-]*)/$', AlbumDetail.as_view(), name='album-detail'),
# url(r'^photos/$', PhotoListCreate.as_view(), name='photo-list'),
# url(r'^optionalrelation/(?P<pk>\d+)/$', OptionalRelationDetail.as_view(), name='optionalrelationmodel-detail'),
# )
# class TestBasicHyperlinkedView(TestCase):
# urls = 'tests.test_hyperlinkedserializers'
# def setUp(self):
# """
# Create 3 BasicModel instances.
# """
# items = ['foo', 'bar', 'baz']
# for item in items:
# BasicModel(text=item).save()
# self.objects = BasicModel.objects
# self.data = [
# {'url': 'http://testserver/basic/%d/' % obj.id, 'text': obj.text}
# for obj in self.objects.all()
# ]
# self.list_view = BasicList.as_view()
# self.detail_view = BasicDetail.as_view()
# def test_get_list_view(self):
# """
# GET requests to ListCreateAPIView should return list of objects.
# """
# request = factory.get('/basic/')
# response = self.list_view(request).render()
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, self.data)
# def test_get_detail_view(self):
# """
# GET requests to ListCreateAPIView should return list of objects.
# """
# request = factory.get('/basic/1')
# response = self.detail_view(request, pk=1).render()
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, self.data[0])
# class TestManyToManyHyperlinkedView(TestCase):
# urls = 'tests.test_hyperlinkedserializers'
# def setUp(self):
# """
# Create 3 BasicModel instances.
# """
# items = ['foo', 'bar', 'baz']
# anchors = []
# for item in items:
# anchor = Anchor(text=item)
# anchor.save()
# anchors.append(anchor)
# manytomany = ManyToManyModel()
# manytomany.save()
# manytomany.rel.add(*anchors)
# self.data = [{
# 'url': 'http://testserver/manytomany/1/',
# 'rel': [
# 'http://testserver/anchor/1/',
# 'http://testserver/anchor/2/',
# 'http://testserver/anchor/3/',
# ]
# }]
# self.list_view = ManyToManyList.as_view()
# self.detail_view = ManyToManyDetail.as_view()
# def test_get_list_view(self):
# """
# GET requests to ListCreateAPIView should return list of objects.
# """
# request = factory.get('/manytomany/')
# response = self.list_view(request)
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, self.data)
# def test_get_detail_view(self):
# """
# GET requests to ListCreateAPIView should return list of objects.
# """
# request = factory.get('/manytomany/1/')
# response = self.detail_view(request, pk=1)
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, self.data[0])
# class TestHyperlinkedIdentityFieldLookup(TestCase):
# urls = 'tests.test_hyperlinkedserializers'
# def setUp(self):
# """
# Create 3 Album instances.
# """
# titles = ['foo', 'bar', 'baz']
# for title in titles:
# album = Album(title=title)
# album.save()
# self.detail_view = AlbumDetail.as_view()
# self.data = {
# 'foo': {'title': 'foo', 'url': 'http://testserver/albums/foo/'},
# 'bar': {'title': 'bar', 'url': 'http://testserver/albums/bar/'},
# 'baz': {'title': 'baz', 'url': 'http://testserver/albums/baz/'}
# }
# def test_lookup_field(self):
# """
# GET requests to AlbumDetail view should return serialized Albums
# with a url field keyed by `title`.
# """
# for album in Album.objects.all():
# request = factory.get('/albums/{0}/'.format(album.title))
# response = self.detail_view(request, title=album.title)
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, self.data[album.title])
# class TestCreateWithForeignKeys(TestCase):
# urls = 'tests.test_hyperlinkedserializers'
# def setUp(self):
# """
# Create a blog post
# """
# self.post = BlogPost.objects.create(title="Test post")
# self.create_view = BlogPostCommentListCreate.as_view()
# def test_create_comment(self):
# data = {
# 'text': 'A test comment',
# 'blog_post_url': 'http://testserver/posts/1/'
# }
# request = factory.post('/comments/', data=data)
# response = self.create_view(request)
# self.assertEqual(response.status_code, status.HTTP_201_CREATED)
# self.assertEqual(response['Location'], 'http://testserver/comments/1/')
# self.assertEqual(self.post.blogpostcomment_set.count(), 1)
# self.assertEqual(self.post.blogpostcomment_set.all()[0].text, 'A test comment')
# class TestCreateWithForeignKeysAndCustomSlug(TestCase):
# urls = 'tests.test_hyperlinkedserializers'
# def setUp(self):
# """
# Create an Album
# """
# self.post = Album.objects.create(title='test-album')
# self.list_create_view = PhotoListCreate.as_view()
# def test_create_photo(self):
# data = {
# 'description': 'A test photo',
# 'album_url': 'http://testserver/albums/test-album/'
# }
# request = factory.post('/photos/', data=data)
# response = self.list_create_view(request)
# self.assertEqual(response.status_code, status.HTTP_201_CREATED)
# self.assertNotIn('Location', response, msg='Location should only be included if there is a "url" field on the serializer')
# self.assertEqual(self.post.photo_set.count(), 1)
# self.assertEqual(self.post.photo_set.all()[0].description, 'A test photo')
# class TestOptionalRelationHyperlinkedView(TestCase):
# urls = 'tests.test_hyperlinkedserializers'
# def setUp(self):
# """
# Create 1 OptionalRelationModel instances.
# """
# OptionalRelationModel().save()
# self.objects = OptionalRelationModel.objects
# self.detail_view = OptionalRelationDetail.as_view()
# self.data = {"url": "http://testserver/optionalrelation/1/", "other": None}
# def test_get_detail_view(self):
# """
# GET requests to RetrieveAPIView with optional relations should return None
# for non existing relations.
# """
# request = factory.get('/optionalrelationmodel-detail/1')
# response = self.detail_view(request, pk=1)
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertEqual(response.data, self.data)
# def test_put_detail_view(self):
# """
# PUT requests to RetrieveUpdateDestroyAPIView with optional relations
# should accept None for non existing relations.
# """
# response = self.client.put('/optionalrelation/1/',
# data=json.dumps(self.data),
# content_type='application/json')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# class TestOverriddenURLField(TestCase):
# def setUp(self):
# class OverriddenURLSerializer(serializers.HyperlinkedModelSerializer):
# url = serializers.SerializerMethodField('get_url')
# class Meta:
# model = BlogPost
# fields = ('title', 'url')
# def get_url(self, obj):
# return 'foo bar'
# self.Serializer = OverriddenURLSerializer
# self.obj = BlogPost.objects.create(title='New blog post')
# def test_overridden_url_field(self):
# """
# The 'url' field should respect overriding.
# Regression test for #936.
# """
# serializer = self.Serializer(self.obj)
# self.assertEqual(
# serializer.data,
# {'title': 'New blog post', 'url': 'foo bar'}
# )
# class TestURLFieldNameBySettings(TestCase):
# urls = 'tests.test_hyperlinkedserializers'
# def setUp(self):
# self.saved_url_field_name = api_settings.URL_FIELD_NAME
# api_settings.URL_FIELD_NAME = 'global_url_field'
# class Serializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = BlogPost
# fields = ('title', api_settings.URL_FIELD_NAME)
# self.Serializer = Serializer
# self.obj = BlogPost.objects.create(title="New blog post")
# def tearDown(self):
# api_settings.URL_FIELD_NAME = self.saved_url_field_name
# def test_overridden_url_field_name(self):
# request = factory.get('/posts/')
# serializer = self.Serializer(self.obj, context={'request': request})
# self.assertIn(api_settings.URL_FIELD_NAME, serializer.data)
# class TestURLFieldNameByOptions(TestCase):
# urls = 'tests.test_hyperlinkedserializers'
# def setUp(self):
# class Serializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = BlogPost
# fields = ('title', 'serializer_url_field')
# url_field_name = 'serializer_url_field'
# self.Serializer = Serializer
# self.obj = BlogPost.objects.create(title="New blog post")
# def test_overridden_url_field_name(self):
# request = factory.get('/posts/')
# serializer = self.Serializer(self.obj, context={'request': request})
# self.assertIn(self.Serializer.Meta.url_field_name, serializer.data)
from django.core.urlresolvers import reverse
# from django.core.urlresolvers import reverse
from django.conf.urls import patterns, url
from rest_framework import serializers, generics
from rest_framework.test import APITestCase
from tests.models import NullableForeignKeySource
# from django.conf.urls import patterns, url
# from rest_framework import serializers, generics
# from rest_framework.test import APITestCase
# from tests.models import NullableForeignKeySource
class NullableFKSourceSerializer(serializers.ModelSerializer):
class Meta:
model = NullableForeignKeySource
# class NullableFKSourceSerializer(serializers.ModelSerializer):
# class Meta:
# model = NullableForeignKeySource
class NullableFKSourceDetail(generics.RetrieveUpdateDestroyAPIView):
queryset = NullableForeignKeySource.objects.all()
serializer_class = NullableFKSourceSerializer
# class NullableFKSourceDetail(generics.RetrieveUpdateDestroyAPIView):
# queryset = NullableForeignKeySource.objects.all()
# serializer_class = NullableFKSourceSerializer
urlpatterns = patterns(
'',
url(r'^objects/(?P<pk>\d+)/$', NullableFKSourceDetail.as_view(), name='object-detail'),
)
# urlpatterns = patterns(
# '',
# url(r'^objects/(?P<pk>\d+)/$', NullableFKSourceDetail.as_view(), name='object-detail'),
# )
class NullableForeignKeyTests(APITestCase):
"""
DRF should be able to handle nullable foreign keys when a test
Client POST/PUT request is made with its own serialized object.
"""
urls = 'tests.test_nullable_fields'
# class NullableForeignKeyTests(APITestCase):
# """
# DRF should be able to handle nullable foreign keys when a test
# Client POST/PUT request is made with its own serialized object.
# """
# urls = 'tests.test_nullable_fields'
def test_updating_object_with_null_fk(self):
obj = NullableForeignKeySource(name='example', target=None)
obj.save()
serialized_data = NullableFKSourceSerializer(obj).data
# def test_updating_object_with_null_fk(self):
# obj = NullableForeignKeySource(name='example', target=None)
# obj.save()
# serialized_data = NullableFKSourceSerializer(obj).data
response = self.client.put(reverse('object-detail', args=[obj.pk]), serialized_data)
# response = self.client.put(reverse('object-detail', args=[obj.pk]), serialized_data)
self.assertEqual(response.data, serialized_data)
# self.assertEqual(response.data, serialized_data)
......@@ -391,10 +391,10 @@ class CustomField(serializers.Field):
class BasicModelSerializer(serializers.Serializer):
text = CustomField()
def __init__(self, *args, **kwargs):
super(BasicModelSerializer, self).__init__(*args, **kwargs)
def to_native(self, value):
if 'view' not in self.context:
raise RuntimeError("context isn't getting passed into serializer init")
raise RuntimeError("context isn't getting passed into serializer")
return super(BasicSerializer, self).to_native(value)
class TestContextPassedToCustomField(TestCase):
......@@ -423,7 +423,7 @@ class LinksSerializer(serializers.Serializer):
class CustomPaginationSerializer(pagination.BasePaginationSerializer):
links = LinksSerializer(source='*') # Takes the page object as the source
total_results = serializers.Field(source='paginator.count')
total_results = serializers.ReadOnlyField(source='paginator.count')
results_field = 'objects'
......
......@@ -108,59 +108,59 @@ class ModelPermissionsIntegrationTests(TestCase):
response = instance_view(request, pk='2')
self.assertEqual(response.status_code, status.HTTP_403_FORBIDDEN)
def test_options_permitted(self):
request = factory.options(
'/',
HTTP_AUTHORIZATION=self.permitted_credentials
)
response = root_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('actions', response.data)
self.assertEqual(list(response.data['actions'].keys()), ['POST'])
request = factory.options(
'/1',
HTTP_AUTHORIZATION=self.permitted_credentials
)
response = instance_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('actions', response.data)
self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
def test_options_disallowed(self):
request = factory.options(
'/',
HTTP_AUTHORIZATION=self.disallowed_credentials
)
response = root_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertNotIn('actions', response.data)
request = factory.options(
'/1',
HTTP_AUTHORIZATION=self.disallowed_credentials
)
response = instance_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertNotIn('actions', response.data)
def test_options_updateonly(self):
request = factory.options(
'/',
HTTP_AUTHORIZATION=self.updateonly_credentials
)
response = root_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertNotIn('actions', response.data)
request = factory.options(
'/1',
HTTP_AUTHORIZATION=self.updateonly_credentials
)
response = instance_view(request, pk='1')
self.assertEqual(response.status_code, status.HTTP_200_OK)
self.assertIn('actions', response.data)
self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
# def test_options_permitted(self):
# request = factory.options(
# '/',
# HTTP_AUTHORIZATION=self.permitted_credentials
# )
# response = root_view(request, pk='1')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertIn('actions', response.data)
# self.assertEqual(list(response.data['actions'].keys()), ['POST'])
# request = factory.options(
# '/1',
# HTTP_AUTHORIZATION=self.permitted_credentials
# )
# response = instance_view(request, pk='1')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertIn('actions', response.data)
# self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
# def test_options_disallowed(self):
# request = factory.options(
# '/',
# HTTP_AUTHORIZATION=self.disallowed_credentials
# )
# response = root_view(request, pk='1')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertNotIn('actions', response.data)
# request = factory.options(
# '/1',
# HTTP_AUTHORIZATION=self.disallowed_credentials
# )
# response = instance_view(request, pk='1')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertNotIn('actions', response.data)
# def test_options_updateonly(self):
# request = factory.options(
# '/',
# HTTP_AUTHORIZATION=self.updateonly_credentials
# )
# response = root_view(request, pk='1')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertNotIn('actions', response.data)
# request = factory.options(
# '/1',
# HTTP_AUTHORIZATION=self.updateonly_credentials
# )
# response = instance_view(request, pk='1')
# self.assertEqual(response.status_code, status.HTTP_200_OK)
# self.assertIn('actions', response.data)
# self.assertEqual(list(response.data['actions'].keys()), ['PUT'])
class BasicPermModel(models.Model):
......
"""
General tests for relational fields.
"""
from __future__ import unicode_literals
from django import get_version
from django.db import models
from django.test import TestCase
from django.utils import unittest
from rest_framework import serializers
from tests.models import BlogPost
class NullModel(models.Model):
pass
class FieldTests(TestCase):
def test_pk_related_field_with_empty_string(self):
"""
Regression test for #446
https://github.com/tomchristie/django-rest-framework/issues/446
"""
field = serializers.PrimaryKeyRelatedField(queryset=NullModel.objects.all())
self.assertRaises(serializers.ValidationError, field.from_native, '')
self.assertRaises(serializers.ValidationError, field.from_native, [])
def test_hyperlinked_related_field_with_empty_string(self):
field = serializers.HyperlinkedRelatedField(queryset=NullModel.objects.all(), view_name='')
self.assertRaises(serializers.ValidationError, field.from_native, '')
self.assertRaises(serializers.ValidationError, field.from_native, [])
def test_slug_related_field_with_empty_string(self):
field = serializers.SlugRelatedField(queryset=NullModel.objects.all(), slug_field='pk')
self.assertRaises(serializers.ValidationError, field.from_native, '')
self.assertRaises(serializers.ValidationError, field.from_native, [])
class TestManyRelatedMixin(TestCase):
def test_missing_many_to_many_related_field(self):
'''
Regression test for #632
https://github.com/tomchristie/django-rest-framework/pull/632
'''
field = serializers.RelatedField(many=True, read_only=False)
into = {}
field.field_from_native({}, None, 'field_name', into)
self.assertEqual(into['field_name'], [])
# Regression tests for #694 (`source` attribute on related fields)
class RelatedFieldSourceTests(TestCase):
def test_related_manager_source(self):
"""
Relational fields should be able to use manager-returning methods as their source.
"""
BlogPost.objects.create(title='blah')
field = serializers.RelatedField(many=True, source='get_blogposts_manager')
class ClassWithManagerMethod(object):
def get_blogposts_manager(self):
return BlogPost.objects
obj = ClassWithManagerMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, ['BlogPost object'])
def test_related_queryset_source(self):
"""
Relational fields should be able to use queryset-returning methods as their source.
"""
BlogPost.objects.create(title='blah')
field = serializers.RelatedField(many=True, source='get_blogposts_queryset')
class ClassWithQuerysetMethod(object):
def get_blogposts_queryset(self):
return BlogPost.objects.all()
obj = ClassWithQuerysetMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, ['BlogPost object'])
def test_dotted_source(self):
"""
Source argument should support dotted.source notation.
"""
BlogPost.objects.create(title='blah')
field = serializers.RelatedField(many=True, source='a.b.c')
class ClassWithQuerysetMethod(object):
a = {
'b': {
'c': BlogPost.objects.all()
}
}
obj = ClassWithQuerysetMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, ['BlogPost object'])
# Regression for #1129
def test_exception_for_incorect_fk(self):
"""
Check that the exception message are correct if the source field
doesn't exist.
"""
from tests.models import ManyToManySource
class Meta:
model = ManyToManySource
attrs = {
'name': serializers.SlugRelatedField(
slug_field='name', source='banzai'),
'Meta': Meta,
}
TestSerializer = type(
str('TestSerializer'),
(serializers.ModelSerializer,),
attrs
)
with self.assertRaises(AttributeError):
TestSerializer(data={'name': 'foo'})
@unittest.skipIf(get_version() < '1.6.0', 'Upstream behaviour changed in v1.6')
class RelatedFieldChoicesTests(TestCase):
"""
Tests for #1408 "Web browseable API doesn't have blank option on drop down list box"
https://github.com/tomchristie/django-rest-framework/issues/1408
"""
def test_blank_option_is_added_to_choice_if_required_equals_false(self):
"""
"""
post = BlogPost(title="Checking blank option is added")
post.save()
queryset = BlogPost.objects.all()
field = serializers.RelatedField(required=False, queryset=queryset)
choice_count = BlogPost.objects.count()
widget_count = len(field.widget.choices)
self.assertEqual(widget_count, choice_count + 1, 'BLANK_CHOICE_DASH option should have been added')
# """
# General tests for relational fields.
# """
# from __future__ import unicode_literals
# from django import get_version
# from django.db import models
# from django.test import TestCase
# from django.utils import unittest
# from rest_framework import serializers
# from tests.models import BlogPost
# class NullModel(models.Model):
# pass
# class FieldTests(TestCase):
# def test_pk_related_field_with_empty_string(self):
# """
# Regression test for #446
# https://github.com/tomchristie/django-rest-framework/issues/446
# """
# field = serializers.PrimaryKeyRelatedField(queryset=NullModel.objects.all())
# self.assertRaises(serializers.ValidationError, field.from_native, '')
# self.assertRaises(serializers.ValidationError, field.from_native, [])
# def test_hyperlinked_related_field_with_empty_string(self):
# field = serializers.HyperlinkedRelatedField(queryset=NullModel.objects.all(), view_name='')
# self.assertRaises(serializers.ValidationError, field.from_native, '')
# self.assertRaises(serializers.ValidationError, field.from_native, [])
# def test_slug_related_field_with_empty_string(self):
# field = serializers.SlugRelatedField(queryset=NullModel.objects.all(), slug_field='pk')
# self.assertRaises(serializers.ValidationError, field.from_native, '')
# self.assertRaises(serializers.ValidationError, field.from_native, [])
# class TestManyRelatedMixin(TestCase):
# def test_missing_many_to_many_related_field(self):
# '''
# Regression test for #632
# https://github.com/tomchristie/django-rest-framework/pull/632
# '''
# field = serializers.RelatedField(many=True, read_only=False)
# into = {}
# field.field_from_native({}, None, 'field_name', into)
# self.assertEqual(into['field_name'], [])
# # Regression tests for #694 (`source` attribute on related fields)
# class RelatedFieldSourceTests(TestCase):
# def test_related_manager_source(self):
# """
# Relational fields should be able to use manager-returning methods as their source.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.RelatedField(many=True, source='get_blogposts_manager')
# class ClassWithManagerMethod(object):
# def get_blogposts_manager(self):
# return BlogPost.objects
# obj = ClassWithManagerMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, ['BlogPost object'])
# def test_related_queryset_source(self):
# """
# Relational fields should be able to use queryset-returning methods as their source.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.RelatedField(many=True, source='get_blogposts_queryset')
# class ClassWithQuerysetMethod(object):
# def get_blogposts_queryset(self):
# return BlogPost.objects.all()
# obj = ClassWithQuerysetMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, ['BlogPost object'])
# def test_dotted_source(self):
# """
# Source argument should support dotted.source notation.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.RelatedField(many=True, source='a.b.c')
# class ClassWithQuerysetMethod(object):
# a = {
# 'b': {
# 'c': BlogPost.objects.all()
# }
# }
# obj = ClassWithQuerysetMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, ['BlogPost object'])
# # Regression for #1129
# def test_exception_for_incorect_fk(self):
# """
# Check that the exception message are correct if the source field
# doesn't exist.
# """
# from tests.models import ManyToManySource
# class Meta:
# model = ManyToManySource
# attrs = {
# 'name': serializers.SlugRelatedField(
# slug_field='name', source='banzai'),
# 'Meta': Meta,
# }
# TestSerializer = type(
# str('TestSerializer'),
# (serializers.ModelSerializer,),
# attrs
# )
# with self.assertRaises(AttributeError):
# TestSerializer(data={'name': 'foo'})
# @unittest.skipIf(get_version() < '1.6.0', 'Upstream behaviour changed in v1.6')
# class RelatedFieldChoicesTests(TestCase):
# """
# Tests for #1408 "Web browseable API doesn't have blank option on drop down list box"
# https://github.com/tomchristie/django-rest-framework/issues/1408
# """
# def test_blank_option_is_added_to_choice_if_required_equals_false(self):
# """
# """
# post = BlogPost(title="Checking blank option is added")
# post.save()
# queryset = BlogPost.objects.all()
# field = serializers.RelatedField(required=False, queryset=queryset)
# choice_count = BlogPost.objects.count()
# widget_count = len(field.widget.choices)
# self.assertEqual(widget_count, choice_count + 1, 'BLANK_CHOICE_DASH option should have been added')
from __future__ import unicode_literals
from django.conf.urls import patterns, url
from django.test import TestCase
from rest_framework import serializers
from rest_framework.test import APIRequestFactory
from tests.models import (
BlogPost,
ManyToManyTarget, ManyToManySource, ForeignKeyTarget, ForeignKeySource,
NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource
)
factory = APIRequestFactory()
request = factory.get('/') # Just to ensure we have a request in the serializer context
def dummy_view(request, pk):
pass
urlpatterns = patterns(
'',
url(r'^dummyurl/(?P<pk>[0-9]+)/$', dummy_view, name='dummy-url'),
url(r'^manytomanysource/(?P<pk>[0-9]+)/$', dummy_view, name='manytomanysource-detail'),
url(r'^manytomanytarget/(?P<pk>[0-9]+)/$', dummy_view, name='manytomanytarget-detail'),
url(r'^foreignkeysource/(?P<pk>[0-9]+)/$', dummy_view, name='foreignkeysource-detail'),
url(r'^foreignkeytarget/(?P<pk>[0-9]+)/$', dummy_view, name='foreignkeytarget-detail'),
url(r'^nullableforeignkeysource/(?P<pk>[0-9]+)/$', dummy_view, name='nullableforeignkeysource-detail'),
url(r'^onetoonetarget/(?P<pk>[0-9]+)/$', dummy_view, name='onetoonetarget-detail'),
url(r'^nullableonetoonesource/(?P<pk>[0-9]+)/$', dummy_view, name='nullableonetoonesource-detail'),
)
# ManyToMany
class ManyToManyTargetSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ManyToManyTarget
fields = ('url', 'name', 'sources')
class ManyToManySourceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ManyToManySource
fields = ('url', 'name', 'targets')
# ForeignKey
class ForeignKeyTargetSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ForeignKeyTarget
fields = ('url', 'name', 'sources')
class ForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = ForeignKeySource
fields = ('url', 'name', 'target')
# Nullable ForeignKey
class NullableForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = NullableForeignKeySource
fields = ('url', 'name', 'target')
# Nullable OneToOne
class NullableOneToOneTargetSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = OneToOneTarget
fields = ('url', 'name', 'nullable_source')
# TODO: Add test that .data cannot be accessed prior to .is_valid
class HyperlinkedManyToManyTests(TestCase):
urls = 'tests.test_relations_hyperlink'
def setUp(self):
for idx in range(1, 4):
target = ManyToManyTarget(name='target-%d' % idx)
target.save()
source = ManyToManySource(name='source-%d' % idx)
source.save()
for target in ManyToManyTarget.objects.all():
source.targets.add(target)
def test_many_to_many_retrieve(self):
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']},
{'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
{'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
]
self.assertEqual(serializer.data, expected)
def test_reverse_many_to_many_retrieve(self):
queryset = ManyToManyTarget.objects.all()
serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
{'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
{'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']}
]
self.assertEqual(serializer.data, expected)
def test_many_to_many_update(self):
data = {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
instance = ManyToManySource.objects.get(pk=1)
serializer = ManyToManySourceSerializer(instance, data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']},
{'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
{'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
]
self.assertEqual(serializer.data, expected)
def test_reverse_many_to_many_update(self):
data = {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/']}
instance = ManyToManyTarget.objects.get(pk=1)
serializer = ManyToManyTargetSerializer(instance, data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure target 1 is updated, and everything else is as expected
queryset = ManyToManyTarget.objects.all()
serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/']},
{'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
{'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']}
]
self.assertEqual(serializer.data, expected)
def test_many_to_many_create(self):
data = {'url': 'http://testserver/manytomanysource/4/', 'name': 'source-4', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/3/']}
serializer = ManyToManySourceSerializer(data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is added, and everything else is as expected
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']},
{'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
{'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']},
{'url': 'http://testserver/manytomanysource/4/', 'name': 'source-4', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/3/']}
]
self.assertEqual(serializer.data, expected)
def test_reverse_many_to_many_create(self):
data = {'url': 'http://testserver/manytomanytarget/4/', 'name': 'target-4', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/3/']}
serializer = ManyToManyTargetSerializer(data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-4')
# Ensure target 4 is added, and everything else is as expected
queryset = ManyToManyTarget.objects.all()
serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
{'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
{'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']},
{'url': 'http://testserver/manytomanytarget/4/', 'name': 'target-4', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/3/']}
]
self.assertEqual(serializer.data, expected)
class HyperlinkedForeignKeyTests(TestCase):
urls = 'tests.test_relations_hyperlink'
def setUp(self):
target = ForeignKeyTarget(name='target-1')
target.save()
new_target = ForeignKeyTarget(name='target-2')
new_target.save()
for idx in range(1, 4):
source = ForeignKeySource(name='source-%d' % idx, target=target)
source.save()
def test_foreign_key_retrieve(self):
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'}
]
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_retrieve(self):
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/2/', 'http://testserver/foreignkeysource/3/']},
{'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update(self):
data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/2/'}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/2/'},
{'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_incorrect_type(self):
data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 2}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected url string, received int.']})
def test_reverse_foreign_key_update(self):
data = {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']}
instance = ForeignKeyTarget.objects.get(pk=2)
serializer = ForeignKeyTargetSerializer(instance, data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
# We shouldn't have saved anything to the db yet since save
# hasn't been called.
queryset = ForeignKeyTarget.objects.all()
new_serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/2/', 'http://testserver/foreignkeysource/3/']},
{'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
]
self.assertEqual(new_serializer.data, expected)
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure target 2 is update, and everything else is as expected
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/2/']},
{'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create(self):
data = {'url': 'http://testserver/foreignkeysource/4/', 'name': 'source-4', 'target': 'http://testserver/foreignkeytarget/2/'}
serializer = ForeignKeySourceSerializer(data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/foreignkeysource/4/', 'name': 'source-4', 'target': 'http://testserver/foreignkeytarget/2/'},
]
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_create(self):
data = {'url': 'http://testserver/foreignkeytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']}
serializer = ForeignKeyTargetSerializer(data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-3')
# Ensure target 4 is added, and everything else is as expected
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/2/']},
{'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
{'url': 'http://testserver/foreignkeytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_invalid_null(self):
data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': None}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'target': ['This field is required.']})
class HyperlinkedNullableForeignKeyTests(TestCase):
urls = 'tests.test_relations_hyperlink'
def setUp(self):
target = ForeignKeyTarget(name='target-1')
target.save()
for idx in range(1, 4):
if idx == 3:
target = None
source = NullableForeignKeySource(name='source-%d' % idx, target=target)
source.save()
def test_foreign_key_retrieve_with_null(self):
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create_with_valid_null(self):
data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
{'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create_with_valid_emptystring(self):
"""
The emptystring should be interpreted as null in the context
of relationships.
"""
data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': ''}
expected_data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, expected_data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
{'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_valid_null(self):
data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None},
{'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_valid_emptystring(self):
"""
The emptystring should be interpreted as null in the context
of relationships.
"""
data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': ''}
expected_data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data, context={'request': request})
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, expected_data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None},
{'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
{'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
]
self.assertEqual(serializer.data, expected)
# reverse foreign keys MUST be read_only
# In the general case they do not provide .remove() or .clear()
# and cannot be arbitrarily set.
# def test_reverse_foreign_key_update(self):
# data = {'id': 1, 'name': 'target-1', 'sources': [1]}
# instance = ForeignKeyTarget.objects.get(pk=1)
# serializer = ForeignKeyTargetSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, data)
# serializer.save()
# # Ensure target 1 is updated, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [1]},
# {'id': 2, 'name': 'target-2', 'sources': []},
# ]
# self.assertEqual(serializer.data, expected)
class HyperlinkedNullableOneToOneTests(TestCase):
urls = 'tests.test_relations_hyperlink'
def setUp(self):
target = OneToOneTarget(name='target-1')
target.save()
new_target = OneToOneTarget(name='target-2')
new_target.save()
source = NullableOneToOneSource(name='source-1', target=target)
source.save()
def test_reverse_foreign_key_retrieve_with_null(self):
queryset = OneToOneTarget.objects.all()
serializer = NullableOneToOneTargetSerializer(queryset, many=True, context={'request': request})
expected = [
{'url': 'http://testserver/onetoonetarget/1/', 'name': 'target-1', 'nullable_source': 'http://testserver/nullableonetoonesource/1/'},
{'url': 'http://testserver/onetoonetarget/2/', 'name': 'target-2', 'nullable_source': None},
]
self.assertEqual(serializer.data, expected)
# Regression tests for #694 (`source` attribute on related fields)
class HyperlinkedRelatedFieldSourceTests(TestCase):
urls = 'tests.test_relations_hyperlink'
def test_related_manager_source(self):
"""
Relational fields should be able to use manager-returning methods as their source.
"""
BlogPost.objects.create(title='blah')
field = serializers.HyperlinkedRelatedField(
many=True,
source='get_blogposts_manager',
view_name='dummy-url',
)
field.context = {'request': request}
class ClassWithManagerMethod(object):
def get_blogposts_manager(self):
return BlogPost.objects
obj = ClassWithManagerMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, ['http://testserver/dummyurl/1/'])
def test_related_queryset_source(self):
"""
Relational fields should be able to use queryset-returning methods as their source.
"""
BlogPost.objects.create(title='blah')
field = serializers.HyperlinkedRelatedField(
many=True,
source='get_blogposts_queryset',
view_name='dummy-url',
)
field.context = {'request': request}
class ClassWithQuerysetMethod(object):
def get_blogposts_queryset(self):
return BlogPost.objects.all()
obj = ClassWithQuerysetMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, ['http://testserver/dummyurl/1/'])
def test_dotted_source(self):
"""
Source argument should support dotted.source notation.
"""
BlogPost.objects.create(title='blah')
field = serializers.HyperlinkedRelatedField(
many=True,
source='a.b.c',
view_name='dummy-url',
)
field.context = {'request': request}
class ClassWithQuerysetMethod(object):
a = {
'b': {
'c': BlogPost.objects.all()
}
}
obj = ClassWithQuerysetMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, ['http://testserver/dummyurl/1/'])
# from __future__ import unicode_literals
# from django.conf.urls import patterns, url
# from django.test import TestCase
# from rest_framework import serializers
# from rest_framework.test import APIRequestFactory
# from tests.models import (
# BlogPost,
# ManyToManyTarget, ManyToManySource, ForeignKeyTarget, ForeignKeySource,
# NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource
# )
# factory = APIRequestFactory()
# request = factory.get('/') # Just to ensure we have a request in the serializer context
# def dummy_view(request, pk):
# pass
# urlpatterns = patterns(
# '',
# url(r'^dummyurl/(?P<pk>[0-9]+)/$', dummy_view, name='dummy-url'),
# url(r'^manytomanysource/(?P<pk>[0-9]+)/$', dummy_view, name='manytomanysource-detail'),
# url(r'^manytomanytarget/(?P<pk>[0-9]+)/$', dummy_view, name='manytomanytarget-detail'),
# url(r'^foreignkeysource/(?P<pk>[0-9]+)/$', dummy_view, name='foreignkeysource-detail'),
# url(r'^foreignkeytarget/(?P<pk>[0-9]+)/$', dummy_view, name='foreignkeytarget-detail'),
# url(r'^nullableforeignkeysource/(?P<pk>[0-9]+)/$', dummy_view, name='nullableforeignkeysource-detail'),
# url(r'^onetoonetarget/(?P<pk>[0-9]+)/$', dummy_view, name='onetoonetarget-detail'),
# url(r'^nullableonetoonesource/(?P<pk>[0-9]+)/$', dummy_view, name='nullableonetoonesource-detail'),
# )
# # ManyToMany
# class ManyToManyTargetSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = ManyToManyTarget
# fields = ('url', 'name', 'sources')
# class ManyToManySourceSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = ManyToManySource
# fields = ('url', 'name', 'targets')
# # ForeignKey
# class ForeignKeyTargetSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = ForeignKeyTarget
# fields = ('url', 'name', 'sources')
# class ForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = ForeignKeySource
# fields = ('url', 'name', 'target')
# # Nullable ForeignKey
# class NullableForeignKeySourceSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = NullableForeignKeySource
# fields = ('url', 'name', 'target')
# # Nullable OneToOne
# class NullableOneToOneTargetSerializer(serializers.HyperlinkedModelSerializer):
# class Meta:
# model = OneToOneTarget
# fields = ('url', 'name', 'nullable_source')
# # TODO: Add test that .data cannot be accessed prior to .is_valid
# class HyperlinkedManyToManyTests(TestCase):
# urls = 'tests.test_relations_hyperlink'
# def setUp(self):
# for idx in range(1, 4):
# target = ManyToManyTarget(name='target-%d' % idx)
# target.save()
# source = ManyToManySource(name='source-%d' % idx)
# source.save()
# for target in ManyToManyTarget.objects.all():
# source.targets.add(target)
# def test_many_to_many_retrieve(self):
# queryset = ManyToManySource.objects.all()
# serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']},
# {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
# {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_many_to_many_retrieve(self):
# queryset = ManyToManyTarget.objects.all()
# serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
# {'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
# {'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']}
# ]
# self.assertEqual(serializer.data, expected)
# def test_many_to_many_update(self):
# data = {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
# instance = ManyToManySource.objects.get(pk=1)
# serializer = ManyToManySourceSerializer(instance, data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# serializer.save()
# self.assertEqual(serializer.data, data)
# # Ensure source 1 is updated, and everything else is as expected
# queryset = ManyToManySource.objects.all()
# serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']},
# {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
# {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']}
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_many_to_many_update(self):
# data = {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/']}
# instance = ManyToManyTarget.objects.get(pk=1)
# serializer = ManyToManyTargetSerializer(instance, data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# serializer.save()
# self.assertEqual(serializer.data, data)
# # Ensure target 1 is updated, and everything else is as expected
# queryset = ManyToManyTarget.objects.all()
# serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/']},
# {'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
# {'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']}
# ]
# self.assertEqual(serializer.data, expected)
# def test_many_to_many_create(self):
# data = {'url': 'http://testserver/manytomanysource/4/', 'name': 'source-4', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/3/']}
# serializer = ManyToManySourceSerializer(data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is added, and everything else is as expected
# queryset = ManyToManySource.objects.all()
# serializer = ManyToManySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/manytomanysource/1/', 'name': 'source-1', 'targets': ['http://testserver/manytomanytarget/1/']},
# {'url': 'http://testserver/manytomanysource/2/', 'name': 'source-2', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/']},
# {'url': 'http://testserver/manytomanysource/3/', 'name': 'source-3', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/2/', 'http://testserver/manytomanytarget/3/']},
# {'url': 'http://testserver/manytomanysource/4/', 'name': 'source-4', 'targets': ['http://testserver/manytomanytarget/1/', 'http://testserver/manytomanytarget/3/']}
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_many_to_many_create(self):
# data = {'url': 'http://testserver/manytomanytarget/4/', 'name': 'target-4', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/3/']}
# serializer = ManyToManyTargetSerializer(data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-4')
# # Ensure target 4 is added, and everything else is as expected
# queryset = ManyToManyTarget.objects.all()
# serializer = ManyToManyTargetSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/manytomanytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
# {'url': 'http://testserver/manytomanytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/manytomanysource/2/', 'http://testserver/manytomanysource/3/']},
# {'url': 'http://testserver/manytomanytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/manytomanysource/3/']},
# {'url': 'http://testserver/manytomanytarget/4/', 'name': 'target-4', 'sources': ['http://testserver/manytomanysource/1/', 'http://testserver/manytomanysource/3/']}
# ]
# self.assertEqual(serializer.data, expected)
# class HyperlinkedForeignKeyTests(TestCase):
# urls = 'tests.test_relations_hyperlink'
# def setUp(self):
# target = ForeignKeyTarget(name='target-1')
# target.save()
# new_target = ForeignKeyTarget(name='target-2')
# new_target.save()
# for idx in range(1, 4):
# source = ForeignKeySource(name='source-%d' % idx, target=target)
# source.save()
# def test_foreign_key_retrieve(self):
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'}
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_foreign_key_retrieve(self):
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/2/', 'http://testserver/foreignkeysource/3/']},
# {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update(self):
# data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/2/'}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/2/'},
# {'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_incorrect_type(self):
# data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 2}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected url string, received int.']})
# def test_reverse_foreign_key_update(self):
# data = {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']}
# instance = ForeignKeyTarget.objects.get(pk=2)
# serializer = ForeignKeyTargetSerializer(instance, data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# # We shouldn't have saved anything to the db yet since save
# # hasn't been called.
# queryset = ForeignKeyTarget.objects.all()
# new_serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/2/', 'http://testserver/foreignkeysource/3/']},
# {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
# ]
# self.assertEqual(new_serializer.data, expected)
# serializer.save()
# self.assertEqual(serializer.data, data)
# # Ensure target 2 is update, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/2/']},
# {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create(self):
# data = {'url': 'http://testserver/foreignkeysource/4/', 'name': 'source-4', 'target': 'http://testserver/foreignkeytarget/2/'}
# serializer = ForeignKeySourceSerializer(data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 1 is updated, and everything else is as expected
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/foreignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/foreignkeysource/3/', 'name': 'source-3', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/foreignkeysource/4/', 'name': 'source-4', 'target': 'http://testserver/foreignkeytarget/2/'},
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_foreign_key_create(self):
# data = {'url': 'http://testserver/foreignkeytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']}
# serializer = ForeignKeyTargetSerializer(data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-3')
# # Ensure target 4 is added, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/foreignkeytarget/1/', 'name': 'target-1', 'sources': ['http://testserver/foreignkeysource/2/']},
# {'url': 'http://testserver/foreignkeytarget/2/', 'name': 'target-2', 'sources': []},
# {'url': 'http://testserver/foreignkeytarget/3/', 'name': 'target-3', 'sources': ['http://testserver/foreignkeysource/1/', 'http://testserver/foreignkeysource/3/']},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_invalid_null(self):
# data = {'url': 'http://testserver/foreignkeysource/1/', 'name': 'source-1', 'target': None}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data, context={'request': request})
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'target': ['This field is required.']})
# class HyperlinkedNullableForeignKeyTests(TestCase):
# urls = 'tests.test_relations_hyperlink'
# def setUp(self):
# target = ForeignKeyTarget(name='target-1')
# target.save()
# for idx in range(1, 4):
# if idx == 3:
# target = None
# source = NullableForeignKeySource(name='source-%d' % idx, target=target)
# source.save()
# def test_foreign_key_retrieve_with_null(self):
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create_with_valid_null(self):
# data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
# serializer = NullableForeignKeySourceSerializer(data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is created, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
# {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create_with_valid_emptystring(self):
# """
# The emptystring should be interpreted as null in the context
# of relationships.
# """
# data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': ''}
# expected_data = {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
# serializer = NullableForeignKeySourceSerializer(data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, expected_data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is created, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
# {'url': 'http://testserver/nullableforeignkeysource/4/', 'name': 'source-4', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_valid_null(self):
# data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}
# instance = NullableForeignKeySource.objects.get(pk=1)
# serializer = NullableForeignKeySourceSerializer(instance, data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None},
# {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_valid_emptystring(self):
# """
# The emptystring should be interpreted as null in the context
# of relationships.
# """
# data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': ''}
# expected_data = {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None}
# instance = NullableForeignKeySource.objects.get(pk=1)
# serializer = NullableForeignKeySourceSerializer(instance, data=data, context={'request': request})
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, expected_data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/nullableforeignkeysource/1/', 'name': 'source-1', 'target': None},
# {'url': 'http://testserver/nullableforeignkeysource/2/', 'name': 'source-2', 'target': 'http://testserver/foreignkeytarget/1/'},
# {'url': 'http://testserver/nullableforeignkeysource/3/', 'name': 'source-3', 'target': None},
# ]
# self.assertEqual(serializer.data, expected)
# # reverse foreign keys MUST be read_only
# # In the general case they do not provide .remove() or .clear()
# # and cannot be arbitrarily set.
# # def test_reverse_foreign_key_update(self):
# # data = {'id': 1, 'name': 'target-1', 'sources': [1]}
# # instance = ForeignKeyTarget.objects.get(pk=1)
# # serializer = ForeignKeyTargetSerializer(instance, data=data)
# # self.assertTrue(serializer.is_valid())
# # self.assertEqual(serializer.data, data)
# # serializer.save()
# # # Ensure target 1 is updated, and everything else is as expected
# # queryset = ForeignKeyTarget.objects.all()
# # serializer = ForeignKeyTargetSerializer(queryset, many=True)
# # expected = [
# # {'id': 1, 'name': 'target-1', 'sources': [1]},
# # {'id': 2, 'name': 'target-2', 'sources': []},
# # ]
# # self.assertEqual(serializer.data, expected)
# class HyperlinkedNullableOneToOneTests(TestCase):
# urls = 'tests.test_relations_hyperlink'
# def setUp(self):
# target = OneToOneTarget(name='target-1')
# target.save()
# new_target = OneToOneTarget(name='target-2')
# new_target.save()
# source = NullableOneToOneSource(name='source-1', target=target)
# source.save()
# def test_reverse_foreign_key_retrieve_with_null(self):
# queryset = OneToOneTarget.objects.all()
# serializer = NullableOneToOneTargetSerializer(queryset, many=True, context={'request': request})
# expected = [
# {'url': 'http://testserver/onetoonetarget/1/', 'name': 'target-1', 'nullable_source': 'http://testserver/nullableonetoonesource/1/'},
# {'url': 'http://testserver/onetoonetarget/2/', 'name': 'target-2', 'nullable_source': None},
# ]
# self.assertEqual(serializer.data, expected)
# # Regression tests for #694 (`source` attribute on related fields)
# class HyperlinkedRelatedFieldSourceTests(TestCase):
# urls = 'tests.test_relations_hyperlink'
# def test_related_manager_source(self):
# """
# Relational fields should be able to use manager-returning methods as their source.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.HyperlinkedRelatedField(
# many=True,
# source='get_blogposts_manager',
# view_name='dummy-url',
# )
# field.context = {'request': request}
# class ClassWithManagerMethod(object):
# def get_blogposts_manager(self):
# return BlogPost.objects
# obj = ClassWithManagerMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, ['http://testserver/dummyurl/1/'])
# def test_related_queryset_source(self):
# """
# Relational fields should be able to use queryset-returning methods as their source.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.HyperlinkedRelatedField(
# many=True,
# source='get_blogposts_queryset',
# view_name='dummy-url',
# )
# field.context = {'request': request}
# class ClassWithQuerysetMethod(object):
# def get_blogposts_queryset(self):
# return BlogPost.objects.all()
# obj = ClassWithQuerysetMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, ['http://testserver/dummyurl/1/'])
# def test_dotted_source(self):
# """
# Source argument should support dotted.source notation.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.HyperlinkedRelatedField(
# many=True,
# source='a.b.c',
# view_name='dummy-url',
# )
# field.context = {'request': request}
# class ClassWithQuerysetMethod(object):
# a = {
# 'b': {
# 'c': BlogPost.objects.all()
# }
# }
# obj = ClassWithQuerysetMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, ['http://testserver/dummyurl/1/'])
from __future__ import unicode_literals
from django.db import models
from django.test import TestCase
from rest_framework import serializers
from .models import OneToOneTarget
class OneToOneSource(models.Model):
name = models.CharField(max_length=100)
target = models.OneToOneField(OneToOneTarget, related_name='source',
null=True, blank=True)
class OneToManyTarget(models.Model):
name = models.CharField(max_length=100)
class OneToManySource(models.Model):
name = models.CharField(max_length=100)
target = models.ForeignKey(OneToManyTarget, related_name='sources')
class ReverseNestedOneToOneTests(TestCase):
def setUp(self):
class OneToOneSourceSerializer(serializers.ModelSerializer):
class Meta:
model = OneToOneSource
fields = ('id', 'name')
class OneToOneTargetSerializer(serializers.ModelSerializer):
source = OneToOneSourceSerializer()
class Meta:
model = OneToOneTarget
fields = ('id', 'name', 'source')
self.Serializer = OneToOneTargetSerializer
for idx in range(1, 4):
target = OneToOneTarget(name='target-%d' % idx)
target.save()
source = OneToOneSource(name='source-%d' % idx, target=target)
source.save()
def test_one_to_one_retrieve(self):
queryset = OneToOneTarget.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'source': {'id': 1, 'name': 'source-1'}},
{'id': 2, 'name': 'target-2', 'source': {'id': 2, 'name': 'source-2'}},
{'id': 3, 'name': 'target-3', 'source': {'id': 3, 'name': 'source-3'}}
]
self.assertEqual(serializer.data, expected)
def test_one_to_one_create(self):
data = {'id': 4, 'name': 'target-4', 'source': {'id': 4, 'name': 'source-4'}}
serializer = self.Serializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-4')
# Ensure (target 4, target_source 4, source 4) are added, and
# everything else is as expected.
queryset = OneToOneTarget.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'source': {'id': 1, 'name': 'source-1'}},
{'id': 2, 'name': 'target-2', 'source': {'id': 2, 'name': 'source-2'}},
{'id': 3, 'name': 'target-3', 'source': {'id': 3, 'name': 'source-3'}},
{'id': 4, 'name': 'target-4', 'source': {'id': 4, 'name': 'source-4'}}
]
self.assertEqual(serializer.data, expected)
def test_one_to_one_create_with_invalid_data(self):
data = {'id': 4, 'name': 'target-4', 'source': {'id': 4}}
serializer = self.Serializer(data=data)
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'source': [{'name': ['This field is required.']}]})
def test_one_to_one_update(self):
data = {'id': 3, 'name': 'target-3-updated', 'source': {'id': 3, 'name': 'source-3-updated'}}
instance = OneToOneTarget.objects.get(pk=3)
serializer = self.Serializer(instance, data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-3-updated')
# Ensure (target 3, target_source 3, source 3) are updated,
# and everything else is as expected.
queryset = OneToOneTarget.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'source': {'id': 1, 'name': 'source-1'}},
{'id': 2, 'name': 'target-2', 'source': {'id': 2, 'name': 'source-2'}},
{'id': 3, 'name': 'target-3-updated', 'source': {'id': 3, 'name': 'source-3-updated'}}
]
self.assertEqual(serializer.data, expected)
class ForwardNestedOneToOneTests(TestCase):
def setUp(self):
class OneToOneTargetSerializer(serializers.ModelSerializer):
class Meta:
model = OneToOneTarget
fields = ('id', 'name')
class OneToOneSourceSerializer(serializers.ModelSerializer):
target = OneToOneTargetSerializer()
class Meta:
model = OneToOneSource
fields = ('id', 'name', 'target')
self.Serializer = OneToOneSourceSerializer
for idx in range(1, 4):
target = OneToOneTarget(name='target-%d' % idx)
target.save()
source = OneToOneSource(name='source-%d' % idx, target=target)
source.save()
def test_one_to_one_retrieve(self):
queryset = OneToOneSource.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
{'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}},
{'id': 3, 'name': 'source-3', 'target': {'id': 3, 'name': 'target-3'}}
]
self.assertEqual(serializer.data, expected)
def test_one_to_one_create(self):
data = {'id': 4, 'name': 'source-4', 'target': {'id': 4, 'name': 'target-4'}}
serializer = self.Serializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure (target 4, target_source 4, source 4) are added, and
# everything else is as expected.
queryset = OneToOneSource.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
{'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}},
{'id': 3, 'name': 'source-3', 'target': {'id': 3, 'name': 'target-3'}},
{'id': 4, 'name': 'source-4', 'target': {'id': 4, 'name': 'target-4'}}
]
self.assertEqual(serializer.data, expected)
def test_one_to_one_create_with_invalid_data(self):
data = {'id': 4, 'name': 'source-4', 'target': {'id': 4}}
serializer = self.Serializer(data=data)
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'target': [{'name': ['This field is required.']}]})
def test_one_to_one_update(self):
data = {'id': 3, 'name': 'source-3-updated', 'target': {'id': 3, 'name': 'target-3-updated'}}
instance = OneToOneSource.objects.get(pk=3)
serializer = self.Serializer(instance, data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-3-updated')
# Ensure (target 3, target_source 3, source 3) are updated,
# and everything else is as expected.
queryset = OneToOneSource.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
{'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}},
{'id': 3, 'name': 'source-3-updated', 'target': {'id': 3, 'name': 'target-3-updated'}}
]
self.assertEqual(serializer.data, expected)
def test_one_to_one_update_to_null(self):
data = {'id': 3, 'name': 'source-3-updated', 'target': None}
instance = OneToOneSource.objects.get(pk=3)
serializer = self.Serializer(instance, data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-3-updated')
self.assertEqual(obj.target, None)
queryset = OneToOneSource.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
{'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}},
{'id': 3, 'name': 'source-3-updated', 'target': None}
]
self.assertEqual(serializer.data, expected)
# TODO: Nullable 1-1 tests
# def test_one_to_one_delete(self):
# data = {'id': 3, 'name': 'target-3', 'target_source': None}
# instance = OneToOneTarget.objects.get(pk=3)
# serializer = self.Serializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# serializer.save()
# # Ensure (target_source 3, source 3) are deleted,
# # and everything else is as expected.
# queryset = OneToOneTarget.objects.all()
# serializer = self.Serializer(queryset)
# expected = [
# {'id': 1, 'name': 'target-1', 'source': {'id': 1, 'name': 'source-1'}},
# {'id': 2, 'name': 'target-2', 'source': {'id': 2, 'name': 'source-2'}},
# {'id': 3, 'name': 'target-3', 'source': None}
# ]
# self.assertEqual(serializer.data, expected)
class ReverseNestedOneToManyTests(TestCase):
def setUp(self):
class OneToManySourceSerializer(serializers.ModelSerializer):
class Meta:
model = OneToManySource
fields = ('id', 'name')
class OneToManyTargetSerializer(serializers.ModelSerializer):
sources = OneToManySourceSerializer(many=True, allow_add_remove=True)
class Meta:
model = OneToManyTarget
fields = ('id', 'name', 'sources')
self.Serializer = OneToManyTargetSerializer
target = OneToManyTarget(name='target-1')
target.save()
for idx in range(1, 4):
source = OneToManySource(name='source-%d' % idx, target=target)
source.save()
def test_one_to_many_retrieve(self):
queryset = OneToManyTarget.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
{'id': 2, 'name': 'source-2'},
{'id': 3, 'name': 'source-3'}]},
]
self.assertEqual(serializer.data, expected)
def test_one_to_many_create(self):
data = {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
{'id': 2, 'name': 'source-2'},
{'id': 3, 'name': 'source-3'},
{'id': 4, 'name': 'source-4'}]}
instance = OneToManyTarget.objects.get(pk=1)
serializer = self.Serializer(instance, data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-1')
# Ensure source 4 is added, and everything else is as
# expected.
queryset = OneToManyTarget.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
{'id': 2, 'name': 'source-2'},
{'id': 3, 'name': 'source-3'},
{'id': 4, 'name': 'source-4'}]}
]
self.assertEqual(serializer.data, expected)
def test_one_to_many_create_with_invalid_data(self):
data = {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
{'id': 2, 'name': 'source-2'},
{'id': 3, 'name': 'source-3'},
{'id': 4}]}
serializer = self.Serializer(data=data)
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'sources': [{}, {}, {}, {'name': ['This field is required.']}]})
def test_one_to_many_update(self):
data = {'id': 1, 'name': 'target-1-updated', 'sources': [{'id': 1, 'name': 'source-1-updated'},
{'id': 2, 'name': 'source-2'},
{'id': 3, 'name': 'source-3'}]}
instance = OneToManyTarget.objects.get(pk=1)
serializer = self.Serializer(instance, data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-1-updated')
# Ensure (target 1, source 1) are updated,
# and everything else is as expected.
queryset = OneToManyTarget.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1-updated', 'sources': [{'id': 1, 'name': 'source-1-updated'},
{'id': 2, 'name': 'source-2'},
{'id': 3, 'name': 'source-3'}]}
]
self.assertEqual(serializer.data, expected)
def test_one_to_many_delete(self):
data = {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
{'id': 3, 'name': 'source-3'}]}
instance = OneToManyTarget.objects.get(pk=1)
serializer = self.Serializer(instance, data=data)
self.assertTrue(serializer.is_valid())
serializer.save()
# Ensure source 2 is deleted, and everything else is as
# expected.
queryset = OneToManyTarget.objects.all()
serializer = self.Serializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
{'id': 3, 'name': 'source-3'}]}
]
self.assertEqual(serializer.data, expected)
# from __future__ import unicode_literals
# from django.db import models
# from django.test import TestCase
# from rest_framework import serializers
# from .models import OneToOneTarget
# class OneToOneSource(models.Model):
# name = models.CharField(max_length=100)
# target = models.OneToOneField(OneToOneTarget, related_name='source',
# null=True, blank=True)
# class OneToManyTarget(models.Model):
# name = models.CharField(max_length=100)
# class OneToManySource(models.Model):
# name = models.CharField(max_length=100)
# target = models.ForeignKey(OneToManyTarget, related_name='sources')
# class ReverseNestedOneToOneTests(TestCase):
# def setUp(self):
# class OneToOneSourceSerializer(serializers.ModelSerializer):
# class Meta:
# model = OneToOneSource
# fields = ('id', 'name')
# class OneToOneTargetSerializer(serializers.ModelSerializer):
# source = OneToOneSourceSerializer()
# class Meta:
# model = OneToOneTarget
# fields = ('id', 'name', 'source')
# self.Serializer = OneToOneTargetSerializer
# for idx in range(1, 4):
# target = OneToOneTarget(name='target-%d' % idx)
# target.save()
# source = OneToOneSource(name='source-%d' % idx, target=target)
# source.save()
# def test_one_to_one_retrieve(self):
# queryset = OneToOneTarget.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'source': {'id': 1, 'name': 'source-1'}},
# {'id': 2, 'name': 'target-2', 'source': {'id': 2, 'name': 'source-2'}},
# {'id': 3, 'name': 'target-3', 'source': {'id': 3, 'name': 'source-3'}}
# ]
# self.assertEqual(serializer.data, expected)
# def test_one_to_one_create(self):
# data = {'id': 4, 'name': 'target-4', 'source': {'id': 4, 'name': 'source-4'}}
# serializer = self.Serializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-4')
# # Ensure (target 4, target_source 4, source 4) are added, and
# # everything else is as expected.
# queryset = OneToOneTarget.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'source': {'id': 1, 'name': 'source-1'}},
# {'id': 2, 'name': 'target-2', 'source': {'id': 2, 'name': 'source-2'}},
# {'id': 3, 'name': 'target-3', 'source': {'id': 3, 'name': 'source-3'}},
# {'id': 4, 'name': 'target-4', 'source': {'id': 4, 'name': 'source-4'}}
# ]
# self.assertEqual(serializer.data, expected)
# def test_one_to_one_create_with_invalid_data(self):
# data = {'id': 4, 'name': 'target-4', 'source': {'id': 4}}
# serializer = self.Serializer(data=data)
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'source': [{'name': ['This field is required.']}]})
# def test_one_to_one_update(self):
# data = {'id': 3, 'name': 'target-3-updated', 'source': {'id': 3, 'name': 'source-3-updated'}}
# instance = OneToOneTarget.objects.get(pk=3)
# serializer = self.Serializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-3-updated')
# # Ensure (target 3, target_source 3, source 3) are updated,
# # and everything else is as expected.
# queryset = OneToOneTarget.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'source': {'id': 1, 'name': 'source-1'}},
# {'id': 2, 'name': 'target-2', 'source': {'id': 2, 'name': 'source-2'}},
# {'id': 3, 'name': 'target-3-updated', 'source': {'id': 3, 'name': 'source-3-updated'}}
# ]
# self.assertEqual(serializer.data, expected)
# class ForwardNestedOneToOneTests(TestCase):
# def setUp(self):
# class OneToOneTargetSerializer(serializers.ModelSerializer):
# class Meta:
# model = OneToOneTarget
# fields = ('id', 'name')
# class OneToOneSourceSerializer(serializers.ModelSerializer):
# target = OneToOneTargetSerializer()
# class Meta:
# model = OneToOneSource
# fields = ('id', 'name', 'target')
# self.Serializer = OneToOneSourceSerializer
# for idx in range(1, 4):
# target = OneToOneTarget(name='target-%d' % idx)
# target.save()
# source = OneToOneSource(name='source-%d' % idx, target=target)
# source.save()
# def test_one_to_one_retrieve(self):
# queryset = OneToOneSource.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
# {'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}},
# {'id': 3, 'name': 'source-3', 'target': {'id': 3, 'name': 'target-3'}}
# ]
# self.assertEqual(serializer.data, expected)
# def test_one_to_one_create(self):
# data = {'id': 4, 'name': 'source-4', 'target': {'id': 4, 'name': 'target-4'}}
# serializer = self.Serializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure (target 4, target_source 4, source 4) are added, and
# # everything else is as expected.
# queryset = OneToOneSource.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
# {'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}},
# {'id': 3, 'name': 'source-3', 'target': {'id': 3, 'name': 'target-3'}},
# {'id': 4, 'name': 'source-4', 'target': {'id': 4, 'name': 'target-4'}}
# ]
# self.assertEqual(serializer.data, expected)
# def test_one_to_one_create_with_invalid_data(self):
# data = {'id': 4, 'name': 'source-4', 'target': {'id': 4}}
# serializer = self.Serializer(data=data)
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'target': [{'name': ['This field is required.']}]})
# def test_one_to_one_update(self):
# data = {'id': 3, 'name': 'source-3-updated', 'target': {'id': 3, 'name': 'target-3-updated'}}
# instance = OneToOneSource.objects.get(pk=3)
# serializer = self.Serializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-3-updated')
# # Ensure (target 3, target_source 3, source 3) are updated,
# # and everything else is as expected.
# queryset = OneToOneSource.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
# {'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}},
# {'id': 3, 'name': 'source-3-updated', 'target': {'id': 3, 'name': 'target-3-updated'}}
# ]
# self.assertEqual(serializer.data, expected)
# def test_one_to_one_update_to_null(self):
# data = {'id': 3, 'name': 'source-3-updated', 'target': None}
# instance = OneToOneSource.objects.get(pk=3)
# serializer = self.Serializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-3-updated')
# self.assertEqual(obj.target, None)
# queryset = OneToOneSource.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': {'id': 1, 'name': 'target-1'}},
# {'id': 2, 'name': 'source-2', 'target': {'id': 2, 'name': 'target-2'}},
# {'id': 3, 'name': 'source-3-updated', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# # TODO: Nullable 1-1 tests
# # def test_one_to_one_delete(self):
# # data = {'id': 3, 'name': 'target-3', 'target_source': None}
# # instance = OneToOneTarget.objects.get(pk=3)
# # serializer = self.Serializer(instance, data=data)
# # self.assertTrue(serializer.is_valid())
# # serializer.save()
# # # Ensure (target_source 3, source 3) are deleted,
# # # and everything else is as expected.
# # queryset = OneToOneTarget.objects.all()
# # serializer = self.Serializer(queryset)
# # expected = [
# # {'id': 1, 'name': 'target-1', 'source': {'id': 1, 'name': 'source-1'}},
# # {'id': 2, 'name': 'target-2', 'source': {'id': 2, 'name': 'source-2'}},
# # {'id': 3, 'name': 'target-3', 'source': None}
# # ]
# # self.assertEqual(serializer.data, expected)
# class ReverseNestedOneToManyTests(TestCase):
# def setUp(self):
# class OneToManySourceSerializer(serializers.ModelSerializer):
# class Meta:
# model = OneToManySource
# fields = ('id', 'name')
# class OneToManyTargetSerializer(serializers.ModelSerializer):
# sources = OneToManySourceSerializer(many=True, allow_add_remove=True)
# class Meta:
# model = OneToManyTarget
# fields = ('id', 'name', 'sources')
# self.Serializer = OneToManyTargetSerializer
# target = OneToManyTarget(name='target-1')
# target.save()
# for idx in range(1, 4):
# source = OneToManySource(name='source-%d' % idx, target=target)
# source.save()
# def test_one_to_many_retrieve(self):
# queryset = OneToManyTarget.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
# {'id': 2, 'name': 'source-2'},
# {'id': 3, 'name': 'source-3'}]},
# ]
# self.assertEqual(serializer.data, expected)
# def test_one_to_many_create(self):
# data = {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
# {'id': 2, 'name': 'source-2'},
# {'id': 3, 'name': 'source-3'},
# {'id': 4, 'name': 'source-4'}]}
# instance = OneToManyTarget.objects.get(pk=1)
# serializer = self.Serializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-1')
# # Ensure source 4 is added, and everything else is as
# # expected.
# queryset = OneToManyTarget.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
# {'id': 2, 'name': 'source-2'},
# {'id': 3, 'name': 'source-3'},
# {'id': 4, 'name': 'source-4'}]}
# ]
# self.assertEqual(serializer.data, expected)
# def test_one_to_many_create_with_invalid_data(self):
# data = {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
# {'id': 2, 'name': 'source-2'},
# {'id': 3, 'name': 'source-3'},
# {'id': 4}]}
# serializer = self.Serializer(data=data)
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'sources': [{}, {}, {}, {'name': ['This field is required.']}]})
# def test_one_to_many_update(self):
# data = {'id': 1, 'name': 'target-1-updated', 'sources': [{'id': 1, 'name': 'source-1-updated'},
# {'id': 2, 'name': 'source-2'},
# {'id': 3, 'name': 'source-3'}]}
# instance = OneToManyTarget.objects.get(pk=1)
# serializer = self.Serializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-1-updated')
# # Ensure (target 1, source 1) are updated,
# # and everything else is as expected.
# queryset = OneToManyTarget.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1-updated', 'sources': [{'id': 1, 'name': 'source-1-updated'},
# {'id': 2, 'name': 'source-2'},
# {'id': 3, 'name': 'source-3'}]}
# ]
# self.assertEqual(serializer.data, expected)
# def test_one_to_many_delete(self):
# data = {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
# {'id': 3, 'name': 'source-3'}]}
# instance = OneToManyTarget.objects.get(pk=1)
# serializer = self.Serializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# serializer.save()
# # Ensure source 2 is deleted, and everything else is as
# # expected.
# queryset = OneToManyTarget.objects.all()
# serializer = self.Serializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [{'id': 1, 'name': 'source-1'},
# {'id': 3, 'name': 'source-3'}]}
# ]
# self.assertEqual(serializer.data, expected)
from __future__ import unicode_literals
from django.db import models
from django.test import TestCase
from django.utils import six
from rest_framework import serializers
from tests.models import (
BlogPost, ManyToManyTarget, ManyToManySource, ForeignKeyTarget, ForeignKeySource,
NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource,
)
# ManyToMany
class ManyToManyTargetSerializer(serializers.ModelSerializer):
class Meta:
model = ManyToManyTarget
fields = ('id', 'name', 'sources')
class ManyToManySourceSerializer(serializers.ModelSerializer):
class Meta:
model = ManyToManySource
fields = ('id', 'name', 'targets')
# ForeignKey
class ForeignKeyTargetSerializer(serializers.ModelSerializer):
class Meta:
model = ForeignKeyTarget
fields = ('id', 'name', 'sources')
class ForeignKeySourceSerializer(serializers.ModelSerializer):
class Meta:
model = ForeignKeySource
fields = ('id', 'name', 'target')
# Nullable ForeignKey
class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
class Meta:
model = NullableForeignKeySource
fields = ('id', 'name', 'target')
# Nullable OneToOne
class NullableOneToOneTargetSerializer(serializers.ModelSerializer):
class Meta:
model = OneToOneTarget
fields = ('id', 'name', 'nullable_source')
# TODO: Add test that .data cannot be accessed prior to .is_valid
class PKManyToManyTests(TestCase):
def setUp(self):
for idx in range(1, 4):
target = ManyToManyTarget(name='target-%d' % idx)
target.save()
source = ManyToManySource(name='source-%d' % idx)
source.save()
for target in ManyToManyTarget.objects.all():
source.targets.add(target)
def test_many_to_many_retrieve(self):
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'targets': [1]},
{'id': 2, 'name': 'source-2', 'targets': [1, 2]},
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
]
self.assertEqual(serializer.data, expected)
def test_reverse_many_to_many_retrieve(self):
queryset = ManyToManyTarget.objects.all()
serializer = ManyToManyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
{'id': 2, 'name': 'target-2', 'sources': [2, 3]},
{'id': 3, 'name': 'target-3', 'sources': [3]}
]
self.assertEqual(serializer.data, expected)
def test_many_to_many_update(self):
data = {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]}
instance = ManyToManySource.objects.get(pk=1)
serializer = ManyToManySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]},
{'id': 2, 'name': 'source-2', 'targets': [1, 2]},
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
]
self.assertEqual(serializer.data, expected)
def test_reverse_many_to_many_update(self):
data = {'id': 1, 'name': 'target-1', 'sources': [1]}
instance = ManyToManyTarget.objects.get(pk=1)
serializer = ManyToManyTargetSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure target 1 is updated, and everything else is as expected
queryset = ManyToManyTarget.objects.all()
serializer = ManyToManyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [1]},
{'id': 2, 'name': 'target-2', 'sources': [2, 3]},
{'id': 3, 'name': 'target-3', 'sources': [3]}
]
self.assertEqual(serializer.data, expected)
def test_many_to_many_create(self):
data = {'id': 4, 'name': 'source-4', 'targets': [1, 3]}
serializer = ManyToManySourceSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is added, and everything else is as expected
queryset = ManyToManySource.objects.all()
serializer = ManyToManySourceSerializer(queryset, many=True)
self.assertFalse(serializer.fields['targets'].read_only)
expected = [
{'id': 1, 'name': 'source-1', 'targets': [1]},
{'id': 2, 'name': 'source-2', 'targets': [1, 2]},
{'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]},
{'id': 4, 'name': 'source-4', 'targets': [1, 3]},
]
self.assertEqual(serializer.data, expected)
def test_reverse_many_to_many_create(self):
data = {'id': 4, 'name': 'target-4', 'sources': [1, 3]}
serializer = ManyToManyTargetSerializer(data=data)
self.assertFalse(serializer.fields['sources'].read_only)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-4')
# Ensure target 4 is added, and everything else is as expected
queryset = ManyToManyTarget.objects.all()
serializer = ManyToManyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
{'id': 2, 'name': 'target-2', 'sources': [2, 3]},
{'id': 3, 'name': 'target-3', 'sources': [3]},
{'id': 4, 'name': 'target-4', 'sources': [1, 3]}
]
self.assertEqual(serializer.data, expected)
class PKForeignKeyTests(TestCase):
def setUp(self):
target = ForeignKeyTarget(name='target-1')
target.save()
new_target = ForeignKeyTarget(name='target-2')
new_target.save()
for idx in range(1, 4):
source = ForeignKeySource(name='source-%d' % idx, target=target)
source.save()
def test_foreign_key_retrieve(self):
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 1},
{'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': 1}
]
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_retrieve(self):
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
{'id': 2, 'name': 'target-2', 'sources': []},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update(self):
data = {'id': 1, 'name': 'source-1', 'target': 2}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 2},
{'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': 1}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_incorrect_type(self):
data = {'id': 1, 'name': 'source-1', 'target': 'foo'}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]})
def test_reverse_foreign_key_update(self):
data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]}
instance = ForeignKeyTarget.objects.get(pk=2)
serializer = ForeignKeyTargetSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
# We shouldn't have saved anything to the db yet since save
# hasn't been called.
queryset = ForeignKeyTarget.objects.all()
new_serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
{'id': 2, 'name': 'target-2', 'sources': []},
]
self.assertEqual(new_serializer.data, expected)
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure target 2 is update, and everything else is as expected
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [2]},
{'id': 2, 'name': 'target-2', 'sources': [1, 3]},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create(self):
data = {'id': 4, 'name': 'source-4', 'target': 2}
serializer = ForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is added, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 1},
{'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': 1},
{'id': 4, 'name': 'source-4', 'target': 2},
]
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_create(self):
data = {'id': 3, 'name': 'target-3', 'sources': [1, 3]}
serializer = ForeignKeyTargetSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-3')
# Ensure target 3 is added, and everything else is as expected
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': [2]},
{'id': 2, 'name': 'target-2', 'sources': []},
{'id': 3, 'name': 'target-3', 'sources': [1, 3]},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_invalid_null(self):
data = {'id': 1, 'name': 'source-1', 'target': None}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'target': ['This field is required.']})
def test_foreign_key_with_empty(self):
"""
Regression test for #1072
https://github.com/tomchristie/django-rest-framework/issues/1072
"""
serializer = NullableForeignKeySourceSerializer()
self.assertEqual(serializer.data['target'], None)
class PKNullableForeignKeyTests(TestCase):
def setUp(self):
target = ForeignKeyTarget(name='target-1')
target.save()
for idx in range(1, 4):
if idx == 3:
target = None
source = NullableForeignKeySource(name='source-%d' % idx, target=target)
source.save()
def test_foreign_key_retrieve_with_null(self):
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 1},
{'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': None},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create_with_valid_null(self):
data = {'id': 4, 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 1},
{'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': None},
{'id': 4, 'name': 'source-4', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create_with_valid_emptystring(self):
"""
The emptystring should be interpreted as null in the context
of relationships.
"""
data = {'id': 4, 'name': 'source-4', 'target': ''}
expected_data = {'id': 4, 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, expected_data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 1},
{'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': None},
{'id': 4, 'name': 'source-4', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_valid_null(self):
data = {'id': 1, 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': None},
{'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_valid_emptystring(self):
"""
The emptystring should be interpreted as null in the context
of relationships.
"""
data = {'id': 1, 'name': 'source-1', 'target': ''}
expected_data = {'id': 1, 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, expected_data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': None},
{'id': 2, 'name': 'source-2', 'target': 1},
{'id': 3, 'name': 'source-3', 'target': None}
]
self.assertEqual(serializer.data, expected)
# reverse foreign keys MUST be read_only
# In the general case they do not provide .remove() or .clear()
# and cannot be arbitrarily set.
# def test_reverse_foreign_key_update(self):
# data = {'id': 1, 'name': 'target-1', 'sources': [1]}
# instance = ForeignKeyTarget.objects.get(pk=1)
# serializer = ForeignKeyTargetSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, data)
# serializer.save()
# # Ensure target 1 is updated, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [1]},
# {'id': 2, 'name': 'target-2', 'sources': []},
# ]
# self.assertEqual(serializer.data, expected)
class PKNullableOneToOneTests(TestCase):
def setUp(self):
target = OneToOneTarget(name='target-1')
target.save()
new_target = OneToOneTarget(name='target-2')
new_target.save()
source = NullableOneToOneSource(name='source-1', target=new_target)
source.save()
def test_reverse_foreign_key_retrieve_with_null(self):
queryset = OneToOneTarget.objects.all()
serializer = NullableOneToOneTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'nullable_source': None},
{'id': 2, 'name': 'target-2', 'nullable_source': 1},
]
self.assertEqual(serializer.data, expected)
# The below models and tests ensure that serializer fields corresponding
# to a ManyToManyField field with a user-specified ``through`` model are
# set to read only
class ManyToManyThroughTarget(models.Model):
name = models.CharField(max_length=100)
class ManyToManyThrough(models.Model):
source = models.ForeignKey('ManyToManyThroughSource')
target = models.ForeignKey(ManyToManyThroughTarget)
class ManyToManyThroughSource(models.Model):
name = models.CharField(max_length=100)
targets = models.ManyToManyField(ManyToManyThroughTarget,
related_name='sources',
through='ManyToManyThrough')
class ManyToManyThroughTargetSerializer(serializers.ModelSerializer):
class Meta:
model = ManyToManyThroughTarget
fields = ('id', 'name', 'sources')
class ManyToManyThroughSourceSerializer(serializers.ModelSerializer):
class Meta:
model = ManyToManyThroughSource
fields = ('id', 'name', 'targets')
class PKManyToManyThroughTests(TestCase):
def setUp(self):
self.source = ManyToManyThroughSource.objects.create(
name='through-source-1')
self.target = ManyToManyThroughTarget.objects.create(
name='through-target-1')
def test_many_to_many_create(self):
data = {'id': 2, 'name': 'source-2', 'targets': [self.target.pk]}
serializer = ManyToManyThroughSourceSerializer(data=data)
self.assertTrue(serializer.fields['targets'].read_only)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(obj.name, 'source-2')
self.assertEqual(obj.targets.count(), 0)
def test_many_to_many_reverse_create(self):
data = {'id': 2, 'name': 'target-2', 'sources': [self.source.pk]}
serializer = ManyToManyThroughTargetSerializer(data=data)
self.assertTrue(serializer.fields['sources'].read_only)
self.assertTrue(serializer.is_valid())
serializer.save()
obj = serializer.save()
self.assertEqual(obj.name, 'target-2')
self.assertEqual(obj.sources.count(), 0)
# Regression tests for #694 (`source` attribute on related fields)
class PrimaryKeyRelatedFieldSourceTests(TestCase):
def test_related_manager_source(self):
"""
Relational fields should be able to use manager-returning methods as their source.
"""
BlogPost.objects.create(title='blah')
field = serializers.PrimaryKeyRelatedField(many=True, source='get_blogposts_manager')
class ClassWithManagerMethod(object):
def get_blogposts_manager(self):
return BlogPost.objects
obj = ClassWithManagerMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, [1])
def test_related_queryset_source(self):
"""
Relational fields should be able to use queryset-returning methods as their source.
"""
BlogPost.objects.create(title='blah')
field = serializers.PrimaryKeyRelatedField(many=True, source='get_blogposts_queryset')
class ClassWithQuerysetMethod(object):
def get_blogposts_queryset(self):
return BlogPost.objects.all()
obj = ClassWithQuerysetMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, [1])
def test_dotted_source(self):
"""
Source argument should support dotted.source notation.
"""
BlogPost.objects.create(title='blah')
field = serializers.PrimaryKeyRelatedField(many=True, source='a.b.c')
class ClassWithQuerysetMethod(object):
a = {
'b': {
'c': BlogPost.objects.all()
}
}
obj = ClassWithQuerysetMethod()
value = field.field_to_native(obj, 'field_name')
self.assertEqual(value, [1])
# from __future__ import unicode_literals
# from django.db import models
# from django.test import TestCase
# from django.utils import six
# from rest_framework import serializers
# from tests.models import (
# BlogPost, ManyToManyTarget, ManyToManySource, ForeignKeyTarget, ForeignKeySource,
# NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource,
# )
# # ManyToMany
# class ManyToManyTargetSerializer(serializers.ModelSerializer):
# class Meta:
# model = ManyToManyTarget
# fields = ('id', 'name', 'sources')
# class ManyToManySourceSerializer(serializers.ModelSerializer):
# class Meta:
# model = ManyToManySource
# fields = ('id', 'name', 'targets')
# # ForeignKey
# class ForeignKeyTargetSerializer(serializers.ModelSerializer):
# class Meta:
# model = ForeignKeyTarget
# fields = ('id', 'name', 'sources')
# class ForeignKeySourceSerializer(serializers.ModelSerializer):
# class Meta:
# model = ForeignKeySource
# fields = ('id', 'name', 'target')
# # Nullable ForeignKey
# class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
# class Meta:
# model = NullableForeignKeySource
# fields = ('id', 'name', 'target')
# # Nullable OneToOne
# class NullableOneToOneTargetSerializer(serializers.ModelSerializer):
# class Meta:
# model = OneToOneTarget
# fields = ('id', 'name', 'nullable_source')
# # TODO: Add test that .data cannot be accessed prior to .is_valid
# class PKManyToManyTests(TestCase):
# def setUp(self):
# for idx in range(1, 4):
# target = ManyToManyTarget(name='target-%d' % idx)
# target.save()
# source = ManyToManySource(name='source-%d' % idx)
# source.save()
# for target in ManyToManyTarget.objects.all():
# source.targets.add(target)
# def test_many_to_many_retrieve(self):
# queryset = ManyToManySource.objects.all()
# serializer = ManyToManySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'targets': [1]},
# {'id': 2, 'name': 'source-2', 'targets': [1, 2]},
# {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_many_to_many_retrieve(self):
# queryset = ManyToManyTarget.objects.all()
# serializer = ManyToManyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
# {'id': 2, 'name': 'target-2', 'sources': [2, 3]},
# {'id': 3, 'name': 'target-3', 'sources': [3]}
# ]
# self.assertEqual(serializer.data, expected)
# def test_many_to_many_update(self):
# data = {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]}
# instance = ManyToManySource.objects.get(pk=1)
# serializer = ManyToManySourceSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# serializer.save()
# self.assertEqual(serializer.data, data)
# # Ensure source 1 is updated, and everything else is as expected
# queryset = ManyToManySource.objects.all()
# serializer = ManyToManySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'targets': [1, 2, 3]},
# {'id': 2, 'name': 'source-2', 'targets': [1, 2]},
# {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]}
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_many_to_many_update(self):
# data = {'id': 1, 'name': 'target-1', 'sources': [1]}
# instance = ManyToManyTarget.objects.get(pk=1)
# serializer = ManyToManyTargetSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# serializer.save()
# self.assertEqual(serializer.data, data)
# # Ensure target 1 is updated, and everything else is as expected
# queryset = ManyToManyTarget.objects.all()
# serializer = ManyToManyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [1]},
# {'id': 2, 'name': 'target-2', 'sources': [2, 3]},
# {'id': 3, 'name': 'target-3', 'sources': [3]}
# ]
# self.assertEqual(serializer.data, expected)
# def test_many_to_many_create(self):
# data = {'id': 4, 'name': 'source-4', 'targets': [1, 3]}
# serializer = ManyToManySourceSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is added, and everything else is as expected
# queryset = ManyToManySource.objects.all()
# serializer = ManyToManySourceSerializer(queryset, many=True)
# self.assertFalse(serializer.fields['targets'].read_only)
# expected = [
# {'id': 1, 'name': 'source-1', 'targets': [1]},
# {'id': 2, 'name': 'source-2', 'targets': [1, 2]},
# {'id': 3, 'name': 'source-3', 'targets': [1, 2, 3]},
# {'id': 4, 'name': 'source-4', 'targets': [1, 3]},
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_many_to_many_create(self):
# data = {'id': 4, 'name': 'target-4', 'sources': [1, 3]}
# serializer = ManyToManyTargetSerializer(data=data)
# self.assertFalse(serializer.fields['sources'].read_only)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-4')
# # Ensure target 4 is added, and everything else is as expected
# queryset = ManyToManyTarget.objects.all()
# serializer = ManyToManyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
# {'id': 2, 'name': 'target-2', 'sources': [2, 3]},
# {'id': 3, 'name': 'target-3', 'sources': [3]},
# {'id': 4, 'name': 'target-4', 'sources': [1, 3]}
# ]
# self.assertEqual(serializer.data, expected)
# class PKForeignKeyTests(TestCase):
# def setUp(self):
# target = ForeignKeyTarget(name='target-1')
# target.save()
# new_target = ForeignKeyTarget(name='target-2')
# new_target.save()
# for idx in range(1, 4):
# source = ForeignKeySource(name='source-%d' % idx, target=target)
# source.save()
# def test_foreign_key_retrieve(self):
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 1},
# {'id': 2, 'name': 'source-2', 'target': 1},
# {'id': 3, 'name': 'source-3', 'target': 1}
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_foreign_key_retrieve(self):
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
# {'id': 2, 'name': 'target-2', 'sources': []},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update(self):
# data = {'id': 1, 'name': 'source-1', 'target': 2}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 2},
# {'id': 2, 'name': 'source-2', 'target': 1},
# {'id': 3, 'name': 'source-3', 'target': 1}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_incorrect_type(self):
# data = {'id': 1, 'name': 'source-1', 'target': 'foo'}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data)
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'target': ['Incorrect type. Expected pk value, received %s.' % six.text_type.__name__]})
# def test_reverse_foreign_key_update(self):
# data = {'id': 2, 'name': 'target-2', 'sources': [1, 3]}
# instance = ForeignKeyTarget.objects.get(pk=2)
# serializer = ForeignKeyTargetSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# # We shouldn't have saved anything to the db yet since save
# # hasn't been called.
# queryset = ForeignKeyTarget.objects.all()
# new_serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [1, 2, 3]},
# {'id': 2, 'name': 'target-2', 'sources': []},
# ]
# self.assertEqual(new_serializer.data, expected)
# serializer.save()
# self.assertEqual(serializer.data, data)
# # Ensure target 2 is update, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [2]},
# {'id': 2, 'name': 'target-2', 'sources': [1, 3]},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create(self):
# data = {'id': 4, 'name': 'source-4', 'target': 2}
# serializer = ForeignKeySourceSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is added, and everything else is as expected
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 1},
# {'id': 2, 'name': 'source-2', 'target': 1},
# {'id': 3, 'name': 'source-3', 'target': 1},
# {'id': 4, 'name': 'source-4', 'target': 2},
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_foreign_key_create(self):
# data = {'id': 3, 'name': 'target-3', 'sources': [1, 3]}
# serializer = ForeignKeyTargetSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-3')
# # Ensure target 3 is added, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': [2]},
# {'id': 2, 'name': 'target-2', 'sources': []},
# {'id': 3, 'name': 'target-3', 'sources': [1, 3]},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_invalid_null(self):
# data = {'id': 1, 'name': 'source-1', 'target': None}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data)
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'target': ['This field is required.']})
# def test_foreign_key_with_empty(self):
# """
# Regression test for #1072
# https://github.com/tomchristie/django-rest-framework/issues/1072
# """
# serializer = NullableForeignKeySourceSerializer()
# self.assertEqual(serializer.data['target'], None)
# class PKNullableForeignKeyTests(TestCase):
# def setUp(self):
# target = ForeignKeyTarget(name='target-1')
# target.save()
# for idx in range(1, 4):
# if idx == 3:
# target = None
# source = NullableForeignKeySource(name='source-%d' % idx, target=target)
# source.save()
# def test_foreign_key_retrieve_with_null(self):
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 1},
# {'id': 2, 'name': 'source-2', 'target': 1},
# {'id': 3, 'name': 'source-3', 'target': None},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create_with_valid_null(self):
# data = {'id': 4, 'name': 'source-4', 'target': None}
# serializer = NullableForeignKeySourceSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is created, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 1},
# {'id': 2, 'name': 'source-2', 'target': 1},
# {'id': 3, 'name': 'source-3', 'target': None},
# {'id': 4, 'name': 'source-4', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create_with_valid_emptystring(self):
# """
# The emptystring should be interpreted as null in the context
# of relationships.
# """
# data = {'id': 4, 'name': 'source-4', 'target': ''}
# expected_data = {'id': 4, 'name': 'source-4', 'target': None}
# serializer = NullableForeignKeySourceSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, expected_data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is created, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 1},
# {'id': 2, 'name': 'source-2', 'target': 1},
# {'id': 3, 'name': 'source-3', 'target': None},
# {'id': 4, 'name': 'source-4', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_valid_null(self):
# data = {'id': 1, 'name': 'source-1', 'target': None}
# instance = NullableForeignKeySource.objects.get(pk=1)
# serializer = NullableForeignKeySourceSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': None},
# {'id': 2, 'name': 'source-2', 'target': 1},
# {'id': 3, 'name': 'source-3', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_valid_emptystring(self):
# """
# The emptystring should be interpreted as null in the context
# of relationships.
# """
# data = {'id': 1, 'name': 'source-1', 'target': ''}
# expected_data = {'id': 1, 'name': 'source-1', 'target': None}
# instance = NullableForeignKeySource.objects.get(pk=1)
# serializer = NullableForeignKeySourceSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, expected_data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': None},
# {'id': 2, 'name': 'source-2', 'target': 1},
# {'id': 3, 'name': 'source-3', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# # reverse foreign keys MUST be read_only
# # In the general case they do not provide .remove() or .clear()
# # and cannot be arbitrarily set.
# # def test_reverse_foreign_key_update(self):
# # data = {'id': 1, 'name': 'target-1', 'sources': [1]}
# # instance = ForeignKeyTarget.objects.get(pk=1)
# # serializer = ForeignKeyTargetSerializer(instance, data=data)
# # self.assertTrue(serializer.is_valid())
# # self.assertEqual(serializer.data, data)
# # serializer.save()
# # # Ensure target 1 is updated, and everything else is as expected
# # queryset = ForeignKeyTarget.objects.all()
# # serializer = ForeignKeyTargetSerializer(queryset, many=True)
# # expected = [
# # {'id': 1, 'name': 'target-1', 'sources': [1]},
# # {'id': 2, 'name': 'target-2', 'sources': []},
# # ]
# # self.assertEqual(serializer.data, expected)
# class PKNullableOneToOneTests(TestCase):
# def setUp(self):
# target = OneToOneTarget(name='target-1')
# target.save()
# new_target = OneToOneTarget(name='target-2')
# new_target.save()
# source = NullableOneToOneSource(name='source-1', target=new_target)
# source.save()
# def test_reverse_foreign_key_retrieve_with_null(self):
# queryset = OneToOneTarget.objects.all()
# serializer = NullableOneToOneTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'nullable_source': None},
# {'id': 2, 'name': 'target-2', 'nullable_source': 1},
# ]
# self.assertEqual(serializer.data, expected)
# # The below models and tests ensure that serializer fields corresponding
# # to a ManyToManyField field with a user-specified ``through`` model are
# # set to read only
# class ManyToManyThroughTarget(models.Model):
# name = models.CharField(max_length=100)
# class ManyToManyThrough(models.Model):
# source = models.ForeignKey('ManyToManyThroughSource')
# target = models.ForeignKey(ManyToManyThroughTarget)
# class ManyToManyThroughSource(models.Model):
# name = models.CharField(max_length=100)
# targets = models.ManyToManyField(ManyToManyThroughTarget,
# related_name='sources',
# through='ManyToManyThrough')
# class ManyToManyThroughTargetSerializer(serializers.ModelSerializer):
# class Meta:
# model = ManyToManyThroughTarget
# fields = ('id', 'name', 'sources')
# class ManyToManyThroughSourceSerializer(serializers.ModelSerializer):
# class Meta:
# model = ManyToManyThroughSource
# fields = ('id', 'name', 'targets')
# class PKManyToManyThroughTests(TestCase):
# def setUp(self):
# self.source = ManyToManyThroughSource.objects.create(
# name='through-source-1')
# self.target = ManyToManyThroughTarget.objects.create(
# name='through-target-1')
# def test_many_to_many_create(self):
# data = {'id': 2, 'name': 'source-2', 'targets': [self.target.pk]}
# serializer = ManyToManyThroughSourceSerializer(data=data)
# self.assertTrue(serializer.fields['targets'].read_only)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(obj.name, 'source-2')
# self.assertEqual(obj.targets.count(), 0)
# def test_many_to_many_reverse_create(self):
# data = {'id': 2, 'name': 'target-2', 'sources': [self.source.pk]}
# serializer = ManyToManyThroughTargetSerializer(data=data)
# self.assertTrue(serializer.fields['sources'].read_only)
# self.assertTrue(serializer.is_valid())
# serializer.save()
# obj = serializer.save()
# self.assertEqual(obj.name, 'target-2')
# self.assertEqual(obj.sources.count(), 0)
# # Regression tests for #694 (`source` attribute on related fields)
# class PrimaryKeyRelatedFieldSourceTests(TestCase):
# def test_related_manager_source(self):
# """
# Relational fields should be able to use manager-returning methods as their source.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.PrimaryKeyRelatedField(many=True, source='get_blogposts_manager')
# class ClassWithManagerMethod(object):
# def get_blogposts_manager(self):
# return BlogPost.objects
# obj = ClassWithManagerMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, [1])
# def test_related_queryset_source(self):
# """
# Relational fields should be able to use queryset-returning methods as their source.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.PrimaryKeyRelatedField(many=True, source='get_blogposts_queryset')
# class ClassWithQuerysetMethod(object):
# def get_blogposts_queryset(self):
# return BlogPost.objects.all()
# obj = ClassWithQuerysetMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, [1])
# def test_dotted_source(self):
# """
# Source argument should support dotted.source notation.
# """
# BlogPost.objects.create(title='blah')
# field = serializers.PrimaryKeyRelatedField(many=True, source='a.b.c')
# class ClassWithQuerysetMethod(object):
# a = {
# 'b': {
# 'c': BlogPost.objects.all()
# }
# }
# obj = ClassWithQuerysetMethod()
# value = field.field_to_native(obj, 'field_name')
# self.assertEqual(value, [1])
from django.test import TestCase
from rest_framework import serializers
from tests.models import NullableForeignKeySource, ForeignKeySource, ForeignKeyTarget
class ForeignKeyTargetSerializer(serializers.ModelSerializer):
sources = serializers.SlugRelatedField(many=True, slug_field='name')
class Meta:
model = ForeignKeyTarget
class ForeignKeySourceSerializer(serializers.ModelSerializer):
target = serializers.SlugRelatedField(slug_field='name')
class Meta:
model = ForeignKeySource
class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
target = serializers.SlugRelatedField(slug_field='name', required=False)
class Meta:
model = NullableForeignKeySource
# TODO: M2M Tests, FKTests (Non-nullable), One2One
class SlugForeignKeyTests(TestCase):
def setUp(self):
target = ForeignKeyTarget(name='target-1')
target.save()
new_target = ForeignKeyTarget(name='target-2')
new_target.save()
for idx in range(1, 4):
source = ForeignKeySource(name='source-%d' % idx, target=target)
source.save()
def test_foreign_key_retrieve(self):
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': 'source-3', 'target': 'target-1'}
]
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_retrieve(self):
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']},
{'id': 2, 'name': 'target-2', 'sources': []},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update(self):
data = {'id': 1, 'name': 'source-1', 'target': 'target-2'}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 'target-2'},
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': 'source-3', 'target': 'target-1'}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_incorrect_type(self):
data = {'id': 1, 'name': 'source-1', 'target': 123}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'target': ['Object with name=123 does not exist.']})
def test_reverse_foreign_key_update(self):
data = {'id': 2, 'name': 'target-2', 'sources': ['source-1', 'source-3']}
instance = ForeignKeyTarget.objects.get(pk=2)
serializer = ForeignKeyTargetSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
# We shouldn't have saved anything to the db yet since save
# hasn't been called.
queryset = ForeignKeyTarget.objects.all()
new_serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']},
{'id': 2, 'name': 'target-2', 'sources': []},
]
self.assertEqual(new_serializer.data, expected)
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure target 2 is update, and everything else is as expected
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': ['source-2']},
{'id': 2, 'name': 'target-2', 'sources': ['source-1', 'source-3']},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create(self):
data = {'id': 4, 'name': 'source-4', 'target': 'target-2'}
serializer = ForeignKeySourceSerializer(data=data)
serializer.is_valid()
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is added, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': 'source-3', 'target': 'target-1'},
{'id': 4, 'name': 'source-4', 'target': 'target-2'},
]
self.assertEqual(serializer.data, expected)
def test_reverse_foreign_key_create(self):
data = {'id': 3, 'name': 'target-3', 'sources': ['source-1', 'source-3']}
serializer = ForeignKeyTargetSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'target-3')
# Ensure target 3 is added, and everything else is as expected
queryset = ForeignKeyTarget.objects.all()
serializer = ForeignKeyTargetSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'target-1', 'sources': ['source-2']},
{'id': 2, 'name': 'target-2', 'sources': []},
{'id': 3, 'name': 'target-3', 'sources': ['source-1', 'source-3']},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_invalid_null(self):
data = {'id': 1, 'name': 'source-1', 'target': None}
instance = ForeignKeySource.objects.get(pk=1)
serializer = ForeignKeySourceSerializer(instance, data=data)
self.assertFalse(serializer.is_valid())
self.assertEqual(serializer.errors, {'target': ['This field is required.']})
class SlugNullableForeignKeyTests(TestCase):
def setUp(self):
target = ForeignKeyTarget(name='target-1')
target.save()
for idx in range(1, 4):
if idx == 3:
target = None
source = NullableForeignKeySource(name='source-%d' % idx, target=target)
source.save()
def test_foreign_key_retrieve_with_null(self):
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': 'source-3', 'target': None},
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create_with_valid_null(self):
data = {'id': 4, 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': 'source-3', 'target': None},
{'id': 4, 'name': 'source-4', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_create_with_valid_emptystring(self):
"""
The emptystring should be interpreted as null in the context
of relationships.
"""
data = {'id': 4, 'name': 'source-4', 'target': ''}
expected_data = {'id': 4, 'name': 'source-4', 'target': None}
serializer = NullableForeignKeySourceSerializer(data=data)
self.assertTrue(serializer.is_valid())
obj = serializer.save()
self.assertEqual(serializer.data, expected_data)
self.assertEqual(obj.name, 'source-4')
# Ensure source 4 is created, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': 'target-1'},
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': 'source-3', 'target': None},
{'id': 4, 'name': 'source-4', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_valid_null(self):
data = {'id': 1, 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': None},
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': 'source-3', 'target': None}
]
self.assertEqual(serializer.data, expected)
def test_foreign_key_update_with_valid_emptystring(self):
"""
The emptystring should be interpreted as null in the context
of relationships.
"""
data = {'id': 1, 'name': 'source-1', 'target': ''}
expected_data = {'id': 1, 'name': 'source-1', 'target': None}
instance = NullableForeignKeySource.objects.get(pk=1)
serializer = NullableForeignKeySourceSerializer(instance, data=data)
self.assertTrue(serializer.is_valid())
self.assertEqual(serializer.data, expected_data)
serializer.save()
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
expected = [
{'id': 1, 'name': 'source-1', 'target': None},
{'id': 2, 'name': 'source-2', 'target': 'target-1'},
{'id': 3, 'name': 'source-3', 'target': None}
]
self.assertEqual(serializer.data, expected)
# from django.test import TestCase
# from rest_framework import serializers
# from tests.models import NullableForeignKeySource, ForeignKeySource, ForeignKeyTarget
# class ForeignKeyTargetSerializer(serializers.ModelSerializer):
# sources = serializers.SlugRelatedField(many=True, slug_field='name')
# class Meta:
# model = ForeignKeyTarget
# class ForeignKeySourceSerializer(serializers.ModelSerializer):
# target = serializers.SlugRelatedField(slug_field='name')
# class Meta:
# model = ForeignKeySource
# class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
# target = serializers.SlugRelatedField(slug_field='name', required=False)
# class Meta:
# model = NullableForeignKeySource
# # TODO: M2M Tests, FKTests (Non-nullable), One2One
# class SlugForeignKeyTests(TestCase):
# def setUp(self):
# target = ForeignKeyTarget(name='target-1')
# target.save()
# new_target = ForeignKeyTarget(name='target-2')
# new_target.save()
# for idx in range(1, 4):
# source = ForeignKeySource(name='source-%d' % idx, target=target)
# source.save()
# def test_foreign_key_retrieve(self):
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 'target-1'},
# {'id': 2, 'name': 'source-2', 'target': 'target-1'},
# {'id': 3, 'name': 'source-3', 'target': 'target-1'}
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_foreign_key_retrieve(self):
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']},
# {'id': 2, 'name': 'target-2', 'sources': []},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update(self):
# data = {'id': 1, 'name': 'source-1', 'target': 'target-2'}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 'target-2'},
# {'id': 2, 'name': 'source-2', 'target': 'target-1'},
# {'id': 3, 'name': 'source-3', 'target': 'target-1'}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_incorrect_type(self):
# data = {'id': 1, 'name': 'source-1', 'target': 123}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data)
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'target': ['Object with name=123 does not exist.']})
# def test_reverse_foreign_key_update(self):
# data = {'id': 2, 'name': 'target-2', 'sources': ['source-1', 'source-3']}
# instance = ForeignKeyTarget.objects.get(pk=2)
# serializer = ForeignKeyTargetSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# # We shouldn't have saved anything to the db yet since save
# # hasn't been called.
# queryset = ForeignKeyTarget.objects.all()
# new_serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': ['source-1', 'source-2', 'source-3']},
# {'id': 2, 'name': 'target-2', 'sources': []},
# ]
# self.assertEqual(new_serializer.data, expected)
# serializer.save()
# self.assertEqual(serializer.data, data)
# # Ensure target 2 is update, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': ['source-2']},
# {'id': 2, 'name': 'target-2', 'sources': ['source-1', 'source-3']},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create(self):
# data = {'id': 4, 'name': 'source-4', 'target': 'target-2'}
# serializer = ForeignKeySourceSerializer(data=data)
# serializer.is_valid()
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is added, and everything else is as expected
# queryset = ForeignKeySource.objects.all()
# serializer = ForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 'target-1'},
# {'id': 2, 'name': 'source-2', 'target': 'target-1'},
# {'id': 3, 'name': 'source-3', 'target': 'target-1'},
# {'id': 4, 'name': 'source-4', 'target': 'target-2'},
# ]
# self.assertEqual(serializer.data, expected)
# def test_reverse_foreign_key_create(self):
# data = {'id': 3, 'name': 'target-3', 'sources': ['source-1', 'source-3']}
# serializer = ForeignKeyTargetSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'target-3')
# # Ensure target 3 is added, and everything else is as expected
# queryset = ForeignKeyTarget.objects.all()
# serializer = ForeignKeyTargetSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'target-1', 'sources': ['source-2']},
# {'id': 2, 'name': 'target-2', 'sources': []},
# {'id': 3, 'name': 'target-3', 'sources': ['source-1', 'source-3']},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_invalid_null(self):
# data = {'id': 1, 'name': 'source-1', 'target': None}
# instance = ForeignKeySource.objects.get(pk=1)
# serializer = ForeignKeySourceSerializer(instance, data=data)
# self.assertFalse(serializer.is_valid())
# self.assertEqual(serializer.errors, {'target': ['This field is required.']})
# class SlugNullableForeignKeyTests(TestCase):
# def setUp(self):
# target = ForeignKeyTarget(name='target-1')
# target.save()
# for idx in range(1, 4):
# if idx == 3:
# target = None
# source = NullableForeignKeySource(name='source-%d' % idx, target=target)
# source.save()
# def test_foreign_key_retrieve_with_null(self):
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 'target-1'},
# {'id': 2, 'name': 'source-2', 'target': 'target-1'},
# {'id': 3, 'name': 'source-3', 'target': None},
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create_with_valid_null(self):
# data = {'id': 4, 'name': 'source-4', 'target': None}
# serializer = NullableForeignKeySourceSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is created, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 'target-1'},
# {'id': 2, 'name': 'source-2', 'target': 'target-1'},
# {'id': 3, 'name': 'source-3', 'target': None},
# {'id': 4, 'name': 'source-4', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_create_with_valid_emptystring(self):
# """
# The emptystring should be interpreted as null in the context
# of relationships.
# """
# data = {'id': 4, 'name': 'source-4', 'target': ''}
# expected_data = {'id': 4, 'name': 'source-4', 'target': None}
# serializer = NullableForeignKeySourceSerializer(data=data)
# self.assertTrue(serializer.is_valid())
# obj = serializer.save()
# self.assertEqual(serializer.data, expected_data)
# self.assertEqual(obj.name, 'source-4')
# # Ensure source 4 is created, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': 'target-1'},
# {'id': 2, 'name': 'source-2', 'target': 'target-1'},
# {'id': 3, 'name': 'source-3', 'target': None},
# {'id': 4, 'name': 'source-4', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_valid_null(self):
# data = {'id': 1, 'name': 'source-1', 'target': None}
# instance = NullableForeignKeySource.objects.get(pk=1)
# serializer = NullableForeignKeySourceSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': None},
# {'id': 2, 'name': 'source-2', 'target': 'target-1'},
# {'id': 3, 'name': 'source-3', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
# def test_foreign_key_update_with_valid_emptystring(self):
# """
# The emptystring should be interpreted as null in the context
# of relationships.
# """
# data = {'id': 1, 'name': 'source-1', 'target': ''}
# expected_data = {'id': 1, 'name': 'source-1', 'target': None}
# instance = NullableForeignKeySource.objects.get(pk=1)
# serializer = NullableForeignKeySourceSerializer(instance, data=data)
# self.assertTrue(serializer.is_valid())
# self.assertEqual(serializer.data, expected_data)
# serializer.save()
# # Ensure source 1 is updated, and everything else is as expected
# queryset = NullableForeignKeySource.objects.all()
# serializer = NullableForeignKeySourceSerializer(queryset, many=True)
# expected = [
# {'id': 1, 'name': 'source-1', 'target': None},
# {'id': 2, 'name': 'source-2', 'target': 'target-1'},
# {'id': 3, 'name': 'source-3', 'target': None}
# ]
# self.assertEqual(serializer.data, expected)
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment