1
0
mirror of https://github.com/django/django.git synced 2024-12-23 01:25:58 +00:00

Fixed #28269 -- Fixed Model.__init__() crash on models with a field that has an instance only descriptor.

Regression in d2a26c1a90.
This commit is contained in:
Adam Johnson 2017-06-04 22:58:24 +01:00 committed by Tim Graham
parent 36f09c8a29
commit ed244199c7
4 changed files with 21 additions and 4 deletions

View File

@ -1,4 +1,5 @@
import copy import copy
import inspect
import warnings import warnings
from bisect import bisect from bisect import bisect
from collections import OrderedDict, defaultdict from collections import OrderedDict, defaultdict
@ -829,7 +830,9 @@ class Options:
@cached_property @cached_property
def _property_names(self): def _property_names(self):
"""Return a set of the names of the properties defined on the model.""" """Return a set of the names of the properties defined on the model."""
return frozenset({ names = []
attr for attr in for name in dir(self.model):
dir(self.model) if isinstance(getattr(self.model, attr), property) attr = inspect.getattr_static(self.model, name)
}) if isinstance(attr, property):
names.append(name)
return frozenset(names)

View File

@ -12,3 +12,6 @@ Bugfixes
* Removed an incorrect deprecation warning about a missing ``renderer`` * Removed an incorrect deprecation warning about a missing ``renderer``
argument if a ``Widget.render()`` method accepts ``**kwargs`` argument if a ``Widget.render()`` method accepts ``**kwargs``
(:ticket:`28265`). (:ticket:`28265`).
* Fixed a regression causing ``Model.__init__()`` to crash if a field has an
instance only descriptor (:ticket:`28269`).

View File

@ -9,6 +9,13 @@ class Relation(models.Model):
pass pass
class InstanceOnlyDescriptor(object):
def __get__(self, instance, cls=None):
if instance is None:
raise AttributeError('Instance only')
return 1
class AbstractPerson(models.Model): class AbstractPerson(models.Model):
# DATA fields # DATA fields
data_abstract = models.CharField(max_length=10) data_abstract = models.CharField(max_length=10)
@ -43,6 +50,8 @@ class AbstractPerson(models.Model):
def test_property(self): def test_property(self):
return 1 return 1
test_instance_only_descriptor = InstanceOnlyDescriptor()
class BasePerson(AbstractPerson): class BasePerson(AbstractPerson):
# DATA fields # DATA fields

View File

@ -276,4 +276,6 @@ class ParentListTests(SimpleTestCase):
class PropertyNamesTests(SimpleTestCase): class PropertyNamesTests(SimpleTestCase):
def test_person(self): def test_person(self):
# Instance only descriptors don't appear in _property_names.
self.assertEqual(AbstractPerson().test_instance_only_descriptor, 1)
self.assertEqual(AbstractPerson._meta._property_names, frozenset(['pk', 'test_property'])) self.assertEqual(AbstractPerson._meta._property_names, frozenset(['pk', 'test_property']))