From 140f8620aea44daa368b244d96c68377716fac7e Mon Sep 17 00:00:00 2001 From: Carl Meyer Date: Thu, 16 Oct 2014 12:16:13 -0600 Subject: [PATCH] Set up serializer fields lazily on-demand. This avoids AppRegistryNotReady problems in Django 1.7 with nested serializers, which are instantiated at import time, possibly before Django's app registry is fully populated. --- rest_framework/serializers.py | 6 +++++- tests/test_relations.py | 5 +++-- tests/test_serializer.py | 4 +++- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/rest_framework/serializers.py b/rest_framework/serializers.py index b3db35823..340c6be01 100644 --- a/rest_framework/serializers.py +++ b/rest_framework/serializers.py @@ -22,6 +22,7 @@ from django.db import models from django.forms import widgets from django.utils import six from django.utils.datastructures import SortedDict +from django.utils.functional import cached_property from django.core.exceptions import ObjectDoesNotExist from rest_framework.settings import api_settings @@ -197,7 +198,6 @@ class BaseSerializer(WritableField): self.init_data = data self.init_files = files self.object = instance - self.fields = self.get_fields() self._data = None self._files = None @@ -212,6 +212,10 @@ class BaseSerializer(WritableField): ##### # Methods to determine which fields to use when (de)serializing objects. + @cached_property + def fields(self): + return self.get_fields() + def get_default_fields(self): """ Return the complete set of default fields for the object, as a dict. diff --git a/tests/test_relations.py b/tests/test_relations.py index bc1db69fc..501a9208f 100644 --- a/tests/test_relations.py +++ b/tests/test_relations.py @@ -102,7 +102,7 @@ class RelatedFieldSourceTests(TestCase): self.assertEqual(value, ['BlogPost object']) # Regression for #1129 - def test_exception_for_incorect_fk(self): + def test_exception_for_incorrect_fk(self): """ Check that the exception message are correct if the source field doesn't exist. @@ -123,8 +123,9 @@ class RelatedFieldSourceTests(TestCase): (serializers.ModelSerializer,), attrs ) + serializer = TestSerializer(data={'name': 'foo'}) with self.assertRaises(AttributeError): - TestSerializer(data={'name': 'foo'}) + serializer.fields @unittest.skipIf(get_version() < '1.6.0', 'Upstream behaviour changed in v1.6') diff --git a/tests/test_serializer.py b/tests/test_serializer.py index 90f37cf2e..e72b723f0 100644 --- a/tests/test_serializer.py +++ b/tests/test_serializer.py @@ -327,7 +327,9 @@ class BasicTests(TestCase): """ Regression test for #652. """ - self.assertRaises(AssertionError, PersonSerializerInvalidReadOnly, []) + serializer = PersonSerializerInvalidReadOnly() + with self.assertRaises(AssertionError): + serializer.fields def test_serializer_data_is_cleared_on_save(self): """