From fb0f987f7de5f01d72c671444df0f95de4706fc6 Mon Sep 17 00:00:00 2001 From: chillaranand Date: Wed, 14 Jun 2017 18:11:02 +0530 Subject: [PATCH] Fixed #27914 -- Added support for nested classes in Field.deconstruct()/__repr__(). --- django/db/models/fields/__init__.py | 4 ++-- tests/model_fields/tests.py | 14 ++++++++++++++ 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/django/db/models/fields/__init__.py b/django/db/models/fields/__init__.py index ac8eb778fa..825440458e 100644 --- a/django/db/models/fields/__init__.py +++ b/django/db/models/fields/__init__.py @@ -191,7 +191,7 @@ class Field(RegisterLookupMixin): def __repr__(self): """Display the module, class, and name of the field.""" - path = '%s.%s' % (self.__class__.__module__, self.__class__.__name__) + path = '%s.%s' % (self.__class__.__module__, self.__class__.__qualname__) name = getattr(self, 'name', None) if name is not None: return '<%s: %s>' % (path, name) @@ -448,7 +448,7 @@ class Field(RegisterLookupMixin): if value is not default: keywords[name] = value # Work out path - we shorten it for known Django core fields - path = "%s.%s" % (self.__class__.__module__, self.__class__.__name__) + path = "%s.%s" % (self.__class__.__module__, self.__class__.__qualname__) if path.startswith("django.db.models.fields.related"): path = path.replace("django.db.models.fields.related", "django.db.models") if path.startswith("django.db.models.fields.files"): diff --git a/tests/model_fields/tests.py b/tests/model_fields/tests.py index 11a2e7d52d..29e1f102ab 100644 --- a/tests/model_fields/tests.py +++ b/tests/model_fields/tests.py @@ -9,6 +9,11 @@ from .models import ( ) +class Nested(): + class Field(models.Field): + pass + + class BasicFieldTests(TestCase): def test_show_hidden_initial(self): @@ -33,6 +38,10 @@ class BasicFieldTests(TestCase): f = models.fields.CharField() self.assertEqual(repr(f), '') + def test_field_repr_nested(self): + """__repr__() uses __qualname__ for nested class support.""" + self.assertEqual(repr(Nested.Field()), '') + def test_field_name(self): """ A defined field name (name="fieldname") is used instead of the model @@ -85,6 +94,11 @@ class BasicFieldTests(TestCase): field._get_default pickle.dumps(field) + def test_deconstruct_nested_field(self): + """deconstruct() uses __qualname__ for nested class support.""" + name, path, args, kwargs = Nested.Field().deconstruct() + self.assertEqual(path, 'model_fields.tests.Nested.Field') + class ChoicesTests(SimpleTestCase):