1
0
mirror of https://github.com/django/django.git synced 2025-06-05 03:29:12 +00:00

Fixed #29076 -- Made Model.refresh_from_db() clear cached relationships even if the related id doesn't change.

This commit is contained in:
Jon Dufresne 2018-01-30 07:43:53 -08:00 committed by Tim Graham
parent 46b3e3ffdc
commit 136bf5c214
3 changed files with 15 additions and 12 deletions

View File

@ -609,13 +609,9 @@ class Model(metaclass=ModelBase):
# This field wasn't refreshed - skip ahead. # This field wasn't refreshed - skip ahead.
continue continue
setattr(self, field.attname, getattr(db_instance, field.attname)) setattr(self, field.attname, getattr(db_instance, field.attname))
# Throw away stale foreign key references. # Clear cached foreign keys.
if field.is_relation and field.is_cached(self): if field.is_relation and field.is_cached(self):
rel_instance = field.get_cached_value(self) field.delete_cached_value(self)
local_val = getattr(db_instance, field.attname)
related_val = None if rel_instance is None else getattr(rel_instance, field.target_field.attname)
if local_val != related_val or (local_val is None and related_val is None):
field.delete_cached_value(self)
# Clear cached relations. # Clear cached relations.
for field in self._meta.related_objects: for field in self._meta.related_objects:

View File

@ -137,12 +137,7 @@ following is done:
1. All non-deferred fields of the model are updated to the values currently 1. All non-deferred fields of the model are updated to the values currently
present in the database. present in the database.
2. The previously loaded related instances for which the relation's value is no 2. Any cached relations are cleared from the reloaded instance.
longer valid are removed from the reloaded instance. For example, if you have
a foreign key from the reloaded instance to another model with name
``Author``, then if ``obj.author_id != obj.author.id``, ``obj.author`` will
be thrown away, and when next accessed it will be reloaded with the value of
``obj.author_id``.
Only fields of the model are reloaded from the database. Other Only fields of the model are reloaded from the database. Other
database-dependent values such as annotations aren't reloaded. Any database-dependent values such as annotations aren't reloaded. Any

View File

@ -722,3 +722,15 @@ class ModelRefreshTests(TestCase):
FeaturedArticle.objects.create(article_id=article.pk) FeaturedArticle.objects.create(article_id=article.pk)
article.refresh_from_db() article.refresh_from_db()
self.assertTrue(hasattr(article, 'featured')) self.assertTrue(hasattr(article, 'featured'))
def test_refresh_clears_one_to_one_field(self):
article = Article.objects.create(
headline='Parrot programs in Python',
pub_date=datetime(2005, 7, 28),
)
featured = FeaturedArticle.objects.create(article_id=article.pk)
self.assertEqual(featured.article.headline, 'Parrot programs in Python')
article.headline = 'Parrot programs in Python 2.0'
article.save()
featured.refresh_from_db()
self.assertEqual(featured.article.headline, 'Parrot programs in Python 2.0')