Commit 093febb9 by Tom Christie

Tests for relational fields

parent 3fa4a189
from django import forms
from django.conf import settings
from django.core import validators
from django.core.exceptions import ValidationError
from django.core.exceptions import ObjectDoesNotExist, ValidationError
from django.utils import six, timezone
from django.utils.datastructures import SortedDict
from django.utils.dateparse import parse_date, parse_datetime, parse_time
......@@ -54,6 +54,8 @@ def get_attribute(instance, attrs):
for attr in attrs:
try:
instance = getattr(instance, attr)
except ObjectDoesNotExist:
return None
except AttributeError as exc:
try:
return instance[attr]
......@@ -108,6 +110,7 @@ class Field(object):
default_validators = []
default_empty_html = empty
initial = None
coerce_blank_to_null = True
def __init__(self, read_only=False, write_only=False,
required=None, default=empty, initial=empty, source=None,
......@@ -245,6 +248,9 @@ class Field(object):
self.fail('required')
return self.get_default()
if data == '' and self.coerce_blank_to_null:
data = None
if data is None:
if not self.allow_null:
self.fail('null')
......@@ -413,6 +419,7 @@ class CharField(Field):
'blank': _('This field may not be blank.')
}
initial = ''
coerce_blank_to_null = False
def __init__(self, **kwargs):
self.allow_blank = kwargs.pop('allow_blank', False)
......
# 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)
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 (
ManyToManyTarget, ManyToManySource, ForeignKeyTarget, ForeignKeySource,
NullableForeignKeySource, OneToOneTarget, NullableOneToOneSource
)
factory = APIRequestFactory()
request = factory.get('/') # Just to ensure we have a request in the serializer context
dummy_view = lambda request, pk: None
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())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True, context={'request': request})
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 may not be null.']})
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())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
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())
serializer.save()
self.assertEqual(serializer.data, expected_data)
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True, context={'request': request})
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)
# 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)
# print serializer.is_valid()
# print serializer.errors
# print serializer
# self.assertTrue(serializer.is_valid())
# serializer.save()
# self.assertEqual(serializer.data, data)
# # 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)
......
# 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
from __future__ import unicode_literals
from django.test import TestCase
from django.utils import six
from rest_framework import serializers
from tests.models import (
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)
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.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())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True)
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 may not be null.']})
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())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
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())
serializer.save()
self.assertEqual(serializer.data, expected_data)
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
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):
......@@ -481,7 +478,6 @@
# 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')
......@@ -490,9 +486,7 @@
# 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)
......
# 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(
slug_field='name',
queryset=ForeignKeySource.objects.all(),
many=True
)
class Meta:
model = ForeignKeyTarget
class ForeignKeySourceSerializer(serializers.ModelSerializer):
target = serializers.SlugRelatedField(
slug_field='name',
queryset=ForeignKeyTarget.objects.all()
)
class Meta:
model = ForeignKeySource
class NullableForeignKeySourceSerializer(serializers.ModelSerializer):
target = serializers.SlugRelatedField(
slug_field='name',
queryset=ForeignKeyTarget.objects.all(),
allow_null=True
)
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())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = ForeignKeySource.objects.all()
serializer = ForeignKeySourceSerializer(queryset, many=True)
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 may not be null.']})
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())
serializer.save()
self.assertEqual(serializer.data, data)
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
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())
serializer.save()
self.assertEqual(serializer.data, expected_data)
# Ensure source 1 is updated, and everything else is as expected
queryset = NullableForeignKeySource.objects.all()
serializer = NullableForeignKeySourceSerializer(queryset, many=True)
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