diff options
| author | Jon Dufresne <jon.dufresne@gmail.com> | 2019-07-23 05:04:06 -0700 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2019-07-25 08:15:20 +0200 |
| commit | 5ed20b3aa3536539b9bc1cb5b40e84e3147a2228 (patch) | |
| tree | 559c955e75e0e30c992eb5836b9eb9aea4b8fed8 /tests | |
| parent | 93ffa81bc59ff13c1a5c07f5bd22d003756e1da5 (diff) | |
Fixed #30657 -- Allowed customizing Field's descriptors with a descriptor_class attribute.
Allows model fields to override the descriptor class used on the model
instance attribute.
Diffstat (limited to 'tests')
| -rw-r--r-- | tests/field_subclassing/fields.py | 20 | ||||
| -rw-r--r-- | tests/field_subclassing/tests.py | 27 |
2 files changed, 45 insertions, 2 deletions
diff --git a/tests/field_subclassing/fields.py b/tests/field_subclassing/fields.py index 4eb170116f..1e255ba9cd 100644 --- a/tests/field_subclassing/fields.py +++ b/tests/field_subclassing/fields.py @@ -1,6 +1,26 @@ from django.db import models +from django.db.models.query_utils import DeferredAttribute class CustomTypedField(models.TextField): def db_type(self, connection): return 'custom_field' + + +class CustomDeferredAttribute(DeferredAttribute): + def __get__(self, instance, cls=None): + self._count_call(instance, 'get') + return super().__get__(instance, cls) + + def __set__(self, instance, value): + self._count_call(instance, 'set') + instance.__dict__[self.field.attname] = value + + def _count_call(self, instance, get_or_set): + count_attr = '_%s_%s_count' % (self.field.attname, get_or_set) + count = getattr(instance, count_attr, 0) + setattr(instance, count_attr, count + 1) + + +class CustomDescriptorField(models.CharField): + descriptor_class = CustomDeferredAttribute diff --git a/tests/field_subclassing/tests.py b/tests/field_subclassing/tests.py index a1371cab42..6d62a5da0e 100644 --- a/tests/field_subclassing/tests.py +++ b/tests/field_subclassing/tests.py @@ -1,7 +1,7 @@ -from django.db import connection +from django.db import connection, models from django.test import SimpleTestCase -from .fields import CustomTypedField +from .fields import CustomDescriptorField, CustomTypedField class TestDbType(SimpleTestCase): @@ -9,3 +9,26 @@ class TestDbType(SimpleTestCase): def test_db_parameters_respects_db_type(self): f = CustomTypedField() self.assertEqual(f.db_parameters(connection)['type'], 'custom_field') + + +class DescriptorClassTest(SimpleTestCase): + def test_descriptor_class(self): + class CustomDescriptorModel(models.Model): + name = CustomDescriptorField(max_length=32) + + m = CustomDescriptorModel() + self.assertFalse(hasattr(m, '_name_get_count')) + # The field is set to its default in the model constructor. + self.assertEqual(m._name_set_count, 1) + m.name = 'foo' + self.assertFalse(hasattr(m, '_name_get_count')) + self.assertEqual(m._name_set_count, 2) + self.assertEqual(m.name, 'foo') + self.assertEqual(m._name_get_count, 1) + self.assertEqual(m._name_set_count, 2) + m.name = 'bar' + self.assertEqual(m._name_get_count, 1) + self.assertEqual(m._name_set_count, 3) + self.assertEqual(m.name, 'bar') + self.assertEqual(m._name_get_count, 2) + self.assertEqual(m._name_set_count, 3) |
