New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed #28198 -- Prevented model attributes from overriding deferred fields. #9126

Open
wants to merge 1 commit into
base: master
from
Jump to file or symbol
Failed to load files and symbols.
+46 −0
Diff settings

Always

Just for now

Copy path View file
@@ -75,6 +75,23 @@ def __new__(cls, name, bases, attrs, **kwargs):
classcell = attrs.pop('__classcell__', None)
if classcell is not None:
new_attrs['__classcell__'] = classcell
# Fixed #28198 -- Model attributes does not overridden by
# attributes from parent classes
# For each parent class collect and remove the attributes which
# present in `attrs` and has implementation in this parent class
duplicate_attributes = {}
for parent in parents:
attributes_per_parent_class = {}
for attr_name in attrs:
if(hasattr(parent, attr_name) and not
attr_name.startswith(LOOKUP_SEP) and not
hasattr(getattr(parent, attr_name), '__dict__')
):
attributes_per_parent_class[attr_name] = getattr(parent, attr_name)
delattr(parent, attr_name)
if len(attributes_per_parent_class) > 0:
duplicate_attributes[parent] = attributes_per_parent_class
new_class = super_new(cls, name, bases, new_attrs, **kwargs)
attr_meta = attrs.pop('Meta', None)
abstract = getattr(attr_meta, 'abstract', False)
@@ -287,6 +304,14 @@ def __new__(cls, name, bases, attrs, **kwargs):
# abstract model.
new_class._meta.indexes = [copy.deepcopy(idx) for idx in new_class._meta.indexes]
# Fixed #28198 -- Model attributes does not overridden by
# attributes from parent classes
# Restore the attributes for each model parent class
if len(duplicate_attributes) > 0:
for parent in parents:
if parent in duplicate_attributes:
for attribute in duplicate_attributes[parent]:
setattr(parent, attribute, duplicate_attributes[parent][attribute])
if abstract:
# Abstract base models can't be instantiated and don't appear in
# the list of models for an app. We do the final setup for them a
Copy path View file
@@ -14,6 +14,7 @@ class Primary(models.Model):
name = models.CharField(max_length=50)
value = models.CharField(max_length=50)
related = models.ForeignKey(Secondary, models.CASCADE)
other = True
def __str__(self):
return self.name
Copy path View file
@@ -271,3 +271,23 @@ def test_custom_refresh_on_deferred_loading(self):
# access of any of them.
self.assertEqual(rf2.name, 'new foo')
self.assertEqual(rf2.value, 'new bar')
def test_field_not_overridden_by_parent(self):
"""
Fixed #28198 -- Model attributes does not overridden by
attributes from parent classes
The defer field `other` must return value from db, instead
attribute value from parent model.
The attribute `other` for Child must be the same
as in parent model
"""
s = Secondary.objects.create()
Child.objects.create(name='foo', value='bar', related=s)
BigChild.objects.create(other="False", related=s)
primary = Child.objects.get()
big_child = BigChild.objects.defer('other').get()
self.assertEqual(len(big_child.get_deferred_fields()), 1)
self.assertIs(primary.other, True)
self.assertEqual(big_child.other, "False")
ProTip! Use n and p to navigate between commits in a pull request.