diff options
| author | Tom Christie | 2014-09-11 13:20:44 +0100 | 
|---|---|---|
| committer | Tom Christie | 2014-09-11 13:20:44 +0100 | 
| commit | de301f3b6647e1c79a506405a88071ef977418d1 (patch) | |
| tree | 407f3497b422f334b47088b0bb35d39a8a3a520a /tests | |
| parent | 80ba0473473501968154c5cc5dd5922e53d96a70 (diff) | |
| parent | 015a8122c7738dd8913939b42d3f0ec932d88711 (diff) | |
| download | django-rest-framework-de301f3b6647e1c79a506405a88071ef977418d1.tar.bz2 | |
Merge master
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/browsable_api/__init__.py | 0 | ||||
| -rw-r--r-- | tests/browsable_api/auth_urls.py | 10 | ||||
| -rw-r--r-- | tests/browsable_api/no_auth_urls.py | 9 | ||||
| -rw-r--r-- | tests/browsable_api/test_browsable_api.py | 65 | ||||
| -rw-r--r-- | tests/browsable_api/views.py | 15 | ||||
| -rw-r--r-- | tests/conftest.py | 1 | ||||
| -rw-r--r-- | tests/test_authentication.py | 12 | ||||
| -rw-r--r-- | tests/test_description.py | 24 | ||||
| -rw-r--r-- | tests/test_fields.py | 20 | ||||
| -rw-r--r-- | tests/test_filters.py | 75 | ||||
| -rw-r--r-- | tests/test_generics.py | 10 | ||||
| -rw-r--r-- | tests/test_model_field_mappings.py | 28 | ||||
| -rw-r--r-- | tests/test_pagination.py | 19 | ||||
| -rw-r--r-- | tests/test_parsers.py | 24 | ||||
| -rw-r--r-- | tests/test_validation.py | 40 | 
15 files changed, 323 insertions, 29 deletions
| diff --git a/tests/browsable_api/__init__.py b/tests/browsable_api/__init__.py new file mode 100644 index 00000000..e69de29b --- /dev/null +++ b/tests/browsable_api/__init__.py diff --git a/tests/browsable_api/auth_urls.py b/tests/browsable_api/auth_urls.py new file mode 100644 index 00000000..bce7dcf9 --- /dev/null +++ b/tests/browsable_api/auth_urls.py @@ -0,0 +1,10 @@ +from __future__ import unicode_literals +from django.conf.urls import patterns, url, include + +from .views import MockView + +urlpatterns = patterns( +    '', +    (r'^$', MockView.as_view()), +    url(r'^auth/', include('rest_framework.urls', namespace='rest_framework')), +) diff --git a/tests/browsable_api/no_auth_urls.py b/tests/browsable_api/no_auth_urls.py new file mode 100644 index 00000000..5e3604a6 --- /dev/null +++ b/tests/browsable_api/no_auth_urls.py @@ -0,0 +1,9 @@ +from __future__ import unicode_literals +from django.conf.urls import patterns + +from .views import MockView + +urlpatterns = patterns( +    '', +    (r'^$', MockView.as_view()), +) diff --git a/tests/browsable_api/test_browsable_api.py b/tests/browsable_api/test_browsable_api.py new file mode 100644 index 00000000..5f264783 --- /dev/null +++ b/tests/browsable_api/test_browsable_api.py @@ -0,0 +1,65 @@ +from __future__ import unicode_literals +from django.contrib.auth.models import User +from django.test import TestCase + +from rest_framework.test import APIClient + + +class DropdownWithAuthTests(TestCase): +    """Tests correct dropdown behaviour with Auth views enabled.""" + +    urls = 'tests.browsable_api.auth_urls' + +    def setUp(self): +        self.client = APIClient(enforce_csrf_checks=True) +        self.username = 'john' +        self.email = 'lennon@thebeatles.com' +        self.password = 'password' +        self.user = User.objects.create_user(self.username, self.email, self.password) + +    def tearDown(self): +        self.client.logout() + +    def test_name_shown_when_logged_in(self): +        self.client.login(username=self.username, password=self.password) +        response = self.client.get('/') +        self.assertContains(response, 'john') + +    def test_logout_shown_when_logged_in(self): +        self.client.login(username=self.username, password=self.password) +        response = self.client.get('/') +        self.assertContains(response, '>Log out<') + +    def test_login_shown_when_logged_out(self): +        response = self.client.get('/') +        self.assertContains(response, '>Log in<') + + +class NoDropdownWithoutAuthTests(TestCase): +    """Tests correct dropdown behaviour with Auth views NOT enabled.""" + +    urls = 'tests.browsable_api.no_auth_urls' + +    def setUp(self): +        self.client = APIClient(enforce_csrf_checks=True) +        self.username = 'john' +        self.email = 'lennon@thebeatles.com' +        self.password = 'password' +        self.user = User.objects.create_user(self.username, self.email, self.password) + +    def tearDown(self): +        self.client.logout() + +    def test_name_shown_when_logged_in(self): +        self.client.login(username=self.username, password=self.password) +        response = self.client.get('/') +        self.assertContains(response, 'john') + +    def test_dropdown_not_shown_when_logged_in(self): +        self.client.login(username=self.username, password=self.password) +        response = self.client.get('/') +        self.assertNotContains(response, '<li class="dropdown">') + +    def test_dropdown_not_shown_when_logged_out(self): +        response = self.client.get('/') +        self.assertNotContains(response, '<li class="dropdown">') diff --git a/tests/browsable_api/views.py b/tests/browsable_api/views.py new file mode 100644 index 00000000..000f4e80 --- /dev/null +++ b/tests/browsable_api/views.py @@ -0,0 +1,15 @@ +from __future__ import unicode_literals + +from rest_framework.views import APIView +from rest_framework import authentication +from rest_framework import renderers +from rest_framework.response import Response + + +class MockView(APIView): + +    authentication_classes = (authentication.SessionAuthentication,) +    renderer_classes = (renderers.BrowsableAPIRenderer,) + +    def get(self, request): +        return Response({'a': 1, 'b': 2, 'c': 3}) diff --git a/tests/conftest.py b/tests/conftest.py index f3723aea..4b33e19c 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ def pytest_configure():          DEBUG_PROPAGATE_EXCEPTIONS=True,          DATABASES={'default': {'ENGINE': 'django.db.backends.sqlite3',                                 'NAME': ':memory:'}}, +        SITE_ID=1,          SECRET_KEY='not very secret in tests',          USE_I18N=True,          USE_L10N=True, diff --git a/tests/test_authentication.py b/tests/test_authentication.py index 2b9d73e4..32041f9c 100644 --- a/tests/test_authentication.py +++ b/tests/test_authentication.py @@ -57,7 +57,8 @@ urlpatterns = patterns(              authentication_classes=[OAuthAuthentication],              permission_classes=[permissions.TokenHasReadWriteScope]          ) -    ) +    ), +    url(r'^auth/', include('rest_framework.urls', namespace='rest_framework'))  ) @@ -134,6 +135,15 @@ class SessionAuthTests(TestCase):      def tearDown(self):          self.csrf_client.logout() +    def test_login_view_renders_on_get(self): +        """ +        Ensure the login template renders for a basic GET. + +        cf. [#1810](https://github.com/tomchristie/django-rest-framework/pull/1810) +        """ +        response = self.csrf_client.get('/auth/login/') +        self.assertContains(response, '<Label class="span4">Username:</label>') +      def test_post_form_session_auth_failing_csrf(self):          """          Ensure POSTing form over session authentication without CSRF token fails. diff --git a/tests/test_description.py b/tests/test_description.py index 1e481f06..0675d209 100644 --- a/tests/test_description.py +++ b/tests/test_description.py @@ -98,6 +98,30 @@ class TestViewNamesAndDescriptions(TestCase):              pass          self.assertEqual(MockView().get_view_description(), '') +    def test_view_description_can_be_promise(self): +        """ +        Ensure a view may have a docstring that is actually a lazily evaluated +        class that can be converted to a string. + +        See: https://github.com/tomchristie/django-rest-framework/issues/1708 +        """ +        # use a mock object instead of gettext_lazy to ensure that we can't end +        # up with a test case string in our l10n catalog +        class MockLazyStr(object): +            def __init__(self, string): +                self.s = string + +            def __str__(self): +                return self.s + +            def __unicode__(self): +                return self.s + +        class MockView(APIView): +            __doc__ = MockLazyStr("a gettext string") + +        self.assertEqual(MockView().get_view_description(), 'a gettext string') +      def test_markdown(self):          """          Ensure markdown to HTML works as expected. diff --git a/tests/test_fields.py b/tests/test_fields.py index 53c60538..a92fafbc 100644 --- a/tests/test_fields.py +++ b/tests/test_fields.py @@ -1012,6 +1012,26 @@  #         def get_my_test(self, obj):  #             return obj.my_test[0:5] +# class ModelCharField(TestCase): +#     """ +#         Tests for CharField +#     """ +#     def test_none_serializing(self): +#         class CharFieldSerializer(serializers.Serializer): +#             char = serializers.CharField(allow_none=True, required=False) +#         serializer = CharFieldSerializer(data={'char': None}) +#         self.assertTrue(serializer.is_valid()) +#         self.assertIsNone(serializer.object['char']) + + +# class SerializerMethodFieldTest(TestCase): +#     """ +#         Tests for the SerializerMethodField field_to_native() behavior +#     """ +#     class SerializerTest(serializers.Serializer): +#         def get_my_test(self, obj): +#             return obj.my_test[0:5] +  #     class Example():  #         my_test = 'Hey, this is a test !' diff --git a/tests/test_filters.py b/tests/test_filters.py index 6f24b1ab..300e47e4 100644 --- a/tests/test_filters.py +++ b/tests/test_filters.py @@ -422,19 +422,70 @@ class SearchFilterTests(TestCase):              ) -class OrdringFilterModel(models.Model): +class OrderingFilterModel(models.Model):      title = models.CharField(max_length=20)      text = models.CharField(max_length=100)  class OrderingFilterRelatedModel(models.Model): -    related_object = models.ForeignKey(OrdringFilterModel, +    related_object = models.ForeignKey(OrderingFilterModel,                                         related_name="relateds")  class OrderingFilterSerializer(serializers.ModelSerializer):      class Meta: -        model = OrdringFilterModel +        model = OrderingFilterModel + + +class DjangoFilterOrderingModel(models.Model): +    date = models.DateField() +    text = models.CharField(max_length=10) + +    class Meta: +        ordering = ['-date'] + + +class DjangoFilterOrderingSerializer(serializers.ModelSerializer): +    class Meta: +        model = DjangoFilterOrderingModel + + +class DjangoFilterOrderingTests(TestCase): +    def setUp(self): +        data = [{ +            'date': datetime.date(2012, 10, 8), +            'text': 'abc' +        }, { +            'date': datetime.date(2013, 10, 8), +            'text': 'bcd' +        }, { +            'date': datetime.date(2014, 10, 8), +            'text': 'cde' +        }] + +        for d in data: +            DjangoFilterOrderingModel.objects.create(**d) + +    def test_default_ordering(self): +        class DjangoFilterOrderingView(generics.ListAPIView): +            serializer_class = DjangoFilterOrderingSerializer +            queryset = DjangoFilterOrderingModel.objects.all() +            filter_backends = (filters.DjangoFilterBackend,) +            filter_fields = ['text'] +            ordering = ('-date',) + +        view = DjangoFilterOrderingView.as_view() +        request = factory.get('/') +        response = view(request) + +        self.assertEqual( +            response.data, +            [ +                {'id': 3, 'date': datetime.date(2014, 10, 8), 'text': 'cde'}, +                {'id': 2, 'date': datetime.date(2013, 10, 8), 'text': 'bcd'}, +                {'id': 1, 'date': datetime.date(2012, 10, 8), 'text': 'abc'} +            ] +        )  class OrderingFilterTests(TestCase): @@ -455,11 +506,11 @@ class OrderingFilterTests(TestCase):                  chr(idx + ord('b')) +                  chr(idx + ord('c'))              ) -            OrdringFilterModel(title=title, text=text).save() +            OrderingFilterModel(title=title, text=text).save()      def test_ordering(self):          class OrderingListView(generics.ListAPIView): -            queryset = OrdringFilterModel.objects.all() +            queryset = OrderingFilterModel.objects.all()              serializer_class = OrderingFilterSerializer              filter_backends = (filters.OrderingFilter,)              ordering = ('title',) @@ -479,7 +530,7 @@ class OrderingFilterTests(TestCase):      def test_reverse_ordering(self):          class OrderingListView(generics.ListAPIView): -            queryset = OrdringFilterModel.objects.all() +            queryset = OrderingFilterModel.objects.all()              serializer_class = OrderingFilterSerializer              filter_backends = (filters.OrderingFilter,)              ordering = ('title',) @@ -499,7 +550,7 @@ class OrderingFilterTests(TestCase):      def test_incorrectfield_ordering(self):          class OrderingListView(generics.ListAPIView): -            queryset = OrdringFilterModel.objects.all() +            queryset = OrderingFilterModel.objects.all()              serializer_class = OrderingFilterSerializer              filter_backends = (filters.OrderingFilter,)              ordering = ('title',) @@ -519,7 +570,7 @@ class OrderingFilterTests(TestCase):      def test_default_ordering(self):          class OrderingListView(generics.ListAPIView): -            queryset = OrdringFilterModel.objects.all() +            queryset = OrderingFilterModel.objects.all()              serializer_class = OrderingFilterSerializer              filter_backends = (filters.OrderingFilter,)              ordering = ('title',) @@ -539,7 +590,7 @@ class OrderingFilterTests(TestCase):      def test_default_ordering_using_string(self):          class OrderingListView(generics.ListAPIView): -            queryset = OrdringFilterModel.objects.all() +            queryset = OrderingFilterModel.objects.all()              serializer_class = OrderingFilterSerializer              filter_backends = (filters.OrderingFilter,)              ordering = 'title' @@ -560,7 +611,7 @@ class OrderingFilterTests(TestCase):      def test_ordering_by_aggregate_field(self):          # create some related models to aggregate order by          num_objs = [2, 5, 3] -        for obj, num_relateds in zip(OrdringFilterModel.objects.all(), +        for obj, num_relateds in zip(OrderingFilterModel.objects.all(),                                       num_objs):              for _ in range(num_relateds):                  new_related = OrderingFilterRelatedModel( @@ -573,7 +624,7 @@ class OrderingFilterTests(TestCase):              filter_backends = (filters.OrderingFilter,)              ordering = 'title'              ordering_fields = '__all__' -            queryset = OrdringFilterModel.objects.all().annotate( +            queryset = OrderingFilterModel.objects.all().annotate(                  models.Count("relateds"))          view = OrderingListView.as_view() @@ -591,7 +642,7 @@ class OrderingFilterTests(TestCase):      def test_ordering_with_nonstandard_ordering_param(self):          with temporary_setting('ORDERING_PARAM', 'order', filters):              class OrderingListView(generics.ListAPIView): -                queryset = OrdringFilterModel.objects.all() +                queryset = OrderingFilterModel.objects.all()                  serializer_class = OrderingFilterSerializer                  filter_backends = (filters.OrderingFilter,)                  ordering = ('title',) diff --git a/tests/test_generics.py b/tests/test_generics.py index 1b00c351..17bfca2f 100644 --- a/tests/test_generics.py +++ b/tests/test_generics.py @@ -1,4 +1,5 @@  from __future__ import unicode_literals +import django  from django.db import models  from django.shortcuts import get_object_or_404  from django.test import TestCase @@ -176,6 +177,9 @@ class TestRootView(TestCase):          self.assertEqual(created.text, 'foobar') +EXPECTED_QUERYS_FOR_PUT = 3 if django.VERSION < (1, 6) else 2 + +  class TestInstanceView(TestCase):      def setUp(self):          """ @@ -219,7 +223,7 @@ class TestInstanceView(TestCase):          """          data = {'text': 'foobar'}          request = factory.put('/1', data, format='json') -        with self.assertNumQueries(3): +        with self.assertNumQueries(EXPECTED_QUERYS_FOR_PUT):              response = self.view(request, pk='1').render()          self.assertEqual(response.status_code, status.HTTP_200_OK)          self.assertEqual(dict(response.data), {'id': 1, 'text': 'foobar'}) @@ -233,7 +237,7 @@ class TestInstanceView(TestCase):          data = {'text': 'foobar'}          request = factory.patch('/1', data, format='json') -        with self.assertNumQueries(3): +        with self.assertNumQueries(EXPECTED_QUERYS_FOR_PUT):              response = self.view(request, pk=1).render()          self.assertEqual(response.status_code, status.HTTP_200_OK)          self.assertEqual(response.data, {'id': 1, 'text': 'foobar'}) @@ -351,7 +355,7 @@ class TestInstanceView(TestCase):          """          data = {'id': 999, 'text': 'foobar'}          request = factory.put('/1', data, format='json') -        with self.assertNumQueries(3): +        with self.assertNumQueries(EXPECTED_QUERYS_FOR_PUT):              response = self.view(request, pk=1).render()          self.assertEqual(response.status_code, status.HTTP_200_OK)          self.assertEqual(response.data, {'id': 1, 'text': 'foobar'}) diff --git a/tests/test_model_field_mappings.py b/tests/test_model_field_mappings.py index dc254da4..57c97cb7 100644 --- a/tests/test_model_field_mappings.py +++ b/tests/test_model_field_mappings.py @@ -15,7 +15,7 @@ from rest_framework import serializers  class RegularFieldsModel(models.Model):      auto_field = models.AutoField(primary_key=True)      big_integer_field = models.BigIntegerField() -    boolean_field = models.BooleanField() +    boolean_field = models.BooleanField(default=False)      char_field = models.CharField(max_length=100)      comma_seperated_integer_field = models.CommaSeparatedIntegerField(max_length=100)      date_field = models.DateField() @@ -60,22 +60,22 @@ TestSerializer():  # Model for testing relational field mapping -class ForeignKeyTarget(models.Model): -    char_field = models.CharField(max_length=100) +class ForeignKeyTargetModel(models.Model): +    name = models.CharField(max_length=100) -class ManyToManyTarget(models.Model): -    char_field = models.CharField(max_length=100) +class ManyToManyTargetModel(models.Model): +    name = models.CharField(max_length=100) -class OneToOneTarget(models.Model): -    char_field = models.CharField(max_length=100) +class OneToOneTargetModel(models.Model): +    name = models.CharField(max_length=100)  class RelationalModel(models.Model): -    foreign_key = models.ForeignKey(ForeignKeyTarget) -    many_to_many = models.ManyToManyField(ManyToManyTarget) -    one_to_one = models.OneToOneField(OneToOneTarget) +    foreign_key = models.ForeignKey(ForeignKeyTargetModel) +    many_to_many = models.ManyToManyField(ManyToManyTargetModel) +    one_to_one = models.OneToOneField(OneToOneTargetModel)  RELATIONAL_FLAT_REPR = """ @@ -105,9 +105,9 @@ TestSerializer():  HYPERLINKED_FLAT_REPR = """  TestSerializer():      url = HyperlinkedIdentityField(view_name='relationalmodel-detail') -    foreign_key = HyperlinkedRelatedField(label='foreign key', queryset=<django.db.models.manager.Manager object>, view_name='foreignkeytarget-detail') -    one_to_one = HyperlinkedRelatedField(label='one to one', queryset=<django.db.models.manager.Manager object>, view_name='onetoonetarget-detail') -    many_to_many = HyperlinkedRelatedField(label='many to many', many=True, queryset=<django.db.models.manager.Manager object>, view_name='manytomanytarget-detail') +    foreign_key = HyperlinkedRelatedField(label='foreign key', queryset=<django.db.models.manager.Manager object>, view_name='foreignkeytargetmodel-detail') +    one_to_one = HyperlinkedRelatedField(label='one to one', queryset=<django.db.models.manager.Manager object>, view_name='onetoonetargetmodel-detail') +    many_to_many = HyperlinkedRelatedField(label='many to many', many=True, queryset=<django.db.models.manager.Manager object>, view_name='manytomanytargetmodel-detail')  """.strip() @@ -127,6 +127,8 @@ TestSerializer():  class TestSerializerMappings(TestCase): +    maxDiff = 10000 +      def test_regular_fields(self):          class TestSerializer(serializers.ModelSerializer):              class Meta: diff --git a/tests/test_pagination.py b/tests/test_pagination.py index 2e56d970..68983ba2 100644 --- a/tests/test_pagination.py +++ b/tests/test_pagination.py @@ -428,6 +428,15 @@ class CustomPaginationSerializer(pagination.BasePaginationSerializer):      results_field = 'objects' +class CustomFooSerializer(serializers.Serializer): +    foo = serializers.CharField() + + +class CustomFooPaginationSerializer(pagination.PaginationSerializer): +    class Meta: +        object_serializer_class = CustomFooSerializer + +  class TestCustomPaginationSerializer(TestCase):      def setUp(self):          objects = ['john', 'paul', 'george', 'ringo'] @@ -450,6 +459,16 @@ class TestCustomPaginationSerializer(TestCase):          }          self.assertEqual(serializer.data, expected) +    def test_custom_pagination_serializer_with_custom_object_serializer(self): +        objects = [ +            {'foo': 'bar'}, +            {'foo': 'spam'} +        ] +        paginator = Paginator(objects, 1) +        page = paginator.page(1) +        serializer = CustomFooPaginationSerializer(page) +        serializer.data +  class NonIntegerPage(object): diff --git a/tests/test_parsers.py b/tests/test_parsers.py index 8af90677..3f2672df 100644 --- a/tests/test_parsers.py +++ b/tests/test_parsers.py @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- +  from __future__ import unicode_literals  from rest_framework.compat import StringIO  from django import forms @@ -113,3 +115,25 @@ class TestFileUploadParser(TestCase):          parser = FileUploadParser()          filename = parser.get_filename(self.stream, None, self.parser_context)          self.assertEqual(filename, 'file.txt') + +    def test_get_encoded_filename(self): +        parser = FileUploadParser() + +        self.__replace_content_disposition('inline; filename*=utf-8\'\'ÀĥƦ.txt') +        filename = parser.get_filename(self.stream, None, self.parser_context) +        self.assertEqual(filename, 'ÀĥƦ.txt') + +        self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8\'\'ÀĥƦ.txt') +        filename = parser.get_filename(self.stream, None, self.parser_context) +        self.assertEqual(filename, 'ÀĥƦ.txt') + +        self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8\'en-us\'ÀĥƦ.txt') +        filename = parser.get_filename(self.stream, None, self.parser_context) +        self.assertEqual(filename, 'ÀĥƦ.txt') + +        self.__replace_content_disposition('inline; filename=fallback.txt; filename*=utf-8--ÀĥƦ.txt') +        filename = parser.get_filename(self.stream, None, self.parser_context) +        self.assertEqual(filename, 'fallback.txt') + +    def __replace_content_disposition(self, disposition): +        self.parser_context['request'].META['HTTP_CONTENT_DISPOSITION'] = disposition diff --git a/tests/test_validation.py b/tests/test_validation.py index 40005486..c4506e7e 100644 --- a/tests/test_validation.py +++ b/tests/test_validation.py @@ -1,5 +1,6 @@  from __future__ import unicode_literals  from django.core.validators import MaxValueValidator +from django.core.exceptions import ValidationError  from django.db import models  from django.test import TestCase  from rest_framework import generics, serializers, status @@ -132,3 +133,42 @@ class TestMaxValueValidatorValidation(TestCase):          response = view(request, pk=obj.pk).render()          self.assertEqual(response.content, b'{"number_value": ["Ensure this value is less than or equal to 100."]}')          self.assertEqual(response.status_code, status.HTTP_400_BAD_REQUEST) + + +class TestChoiceFieldChoicesValidate(TestCase): +    CHOICES = [ +        (0, 'Small'), +        (1, 'Medium'), +        (2, 'Large'), +    ] + +    CHOICES_NESTED = [ +        ('Category', ( +            (1, 'First'), +            (2, 'Second'), +            (3, 'Third'), +        )), +        (4, 'Fourth'), +    ] + +    def test_choices(self): +        """ +        Make sure a value for choices works as expected. +        """ +        f = serializers.ChoiceField(choices=self.CHOICES) +        value = self.CHOICES[0][0] +        try: +            f.to_native(value) +        except ValidationError: +            self.fail("Value %s does not validate" % str(value)) + +    # def test_nested_choices(self): +    #     """ +    #     Make sure a nested value for choices works as expected. +    #     """ +    #     f = serializers.ChoiceField(choices=self.CHOICES_NESTED) +    #     value = self.CHOICES_NESTED[0][1][0][0] +    #     try: +    #         f.to_native(value) +    #     except ValidationError: +    #         self.fail("Value %s does not validate" % str(value)) | 
