Fixed #26362 -- Fixed update of the inherited id field of an object when its parent changes.
This commit is contained in:
parent
fa283067c9
commit
c432927160
|
@ -277,6 +277,22 @@ class ForwardOneToOneDescriptor(ForwardManyToOneDescriptor):
|
||||||
return obj
|
return obj
|
||||||
return super().get_object(instance)
|
return super().get_object(instance)
|
||||||
|
|
||||||
|
def __set__(self, instance, value):
|
||||||
|
super().__set__(instance, value)
|
||||||
|
# If the primary key is a link to a parent model and a parent instance
|
||||||
|
# is being set, update the value of the inherited pk(s).
|
||||||
|
if self.field.primary_key and self.field.remote_field.parent_link:
|
||||||
|
opts = instance._meta
|
||||||
|
# Inherited primary key fields from this object's base classes.
|
||||||
|
inherited_pk_fields = [
|
||||||
|
field for field in opts.concrete_fields
|
||||||
|
if field.primary_key and field.remote_field
|
||||||
|
]
|
||||||
|
for field in inherited_pk_fields:
|
||||||
|
rel_model_pk_name = field.remote_field.model._meta.pk.attname
|
||||||
|
raw_value = getattr(value, rel_model_pk_name) if value is not None else None
|
||||||
|
setattr(instance, rel_model_pk_name, raw_value)
|
||||||
|
|
||||||
|
|
||||||
class ReverseOneToOneDescriptor:
|
class ReverseOneToOneDescriptor:
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -527,3 +527,40 @@ class ModelInheritanceTest(TestCase):
|
||||||
restaurant = italian_restaurant.restaurant_ptr
|
restaurant = italian_restaurant.restaurant_ptr
|
||||||
self.assertEqual(restaurant.place_ptr.restaurant, restaurant)
|
self.assertEqual(restaurant.place_ptr.restaurant, restaurant)
|
||||||
self.assertEqual(restaurant.italianrestaurant, italian_restaurant)
|
self.assertEqual(restaurant.italianrestaurant, italian_restaurant)
|
||||||
|
|
||||||
|
def test_id_field_update_on_ancestor_change(self):
|
||||||
|
place1 = Place.objects.create(name='House of Pasta', address='944 Fullerton')
|
||||||
|
place2 = Place.objects.create(name='House of Pizza', address='954 Fullerton')
|
||||||
|
place3 = Place.objects.create(name='Burger house', address='964 Fullerton')
|
||||||
|
restaurant1 = Restaurant.objects.create(
|
||||||
|
place_ptr=place1,
|
||||||
|
serves_hot_dogs=True,
|
||||||
|
serves_pizza=False,
|
||||||
|
)
|
||||||
|
restaurant2 = Restaurant.objects.create(
|
||||||
|
place_ptr=place2,
|
||||||
|
serves_hot_dogs=True,
|
||||||
|
serves_pizza=False,
|
||||||
|
)
|
||||||
|
|
||||||
|
italian_restaurant = ItalianRestaurant.objects.create(
|
||||||
|
restaurant_ptr=restaurant1,
|
||||||
|
serves_gnocchi=True,
|
||||||
|
)
|
||||||
|
# Changing the parent of a restaurant changes the restaurant's ID & PK.
|
||||||
|
restaurant1.place_ptr = place3
|
||||||
|
self.assertEqual(restaurant1.pk, place3.pk)
|
||||||
|
self.assertEqual(restaurant1.id, place3.id)
|
||||||
|
self.assertEqual(restaurant1.pk, restaurant1.id)
|
||||||
|
restaurant1.place_ptr = None
|
||||||
|
self.assertIsNone(restaurant1.pk)
|
||||||
|
self.assertIsNone(restaurant1.id)
|
||||||
|
# Changing the parent of an italian restaurant changes the restaurant's
|
||||||
|
# ID & PK.
|
||||||
|
italian_restaurant.restaurant_ptr = restaurant2
|
||||||
|
self.assertEqual(italian_restaurant.pk, restaurant2.pk)
|
||||||
|
self.assertEqual(italian_restaurant.id, restaurant2.id)
|
||||||
|
self.assertEqual(italian_restaurant.pk, italian_restaurant.id)
|
||||||
|
italian_restaurant.restaurant_ptr = None
|
||||||
|
self.assertIsNone(italian_restaurant.pk)
|
||||||
|
self.assertIsNone(italian_restaurant.id)
|
||||||
|
|
Loading…
Reference in New Issue