summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJon Dufresne <jon.dufresne@gmail.com>2018-01-30 07:43:53 -0800
committerTim Graham <timograham@gmail.com>2018-01-30 10:43:53 -0500
commit136bf5c2142ae3261669d02e2dd050c3141f7f2f (patch)
tree81781bf9c8401ca911cfd5037c2786137bc13459
parent46b3e3ffdc25b5a42762df20e536401fc512c5f3 (diff)
Fixed #29076 -- Made Model.refresh_from_db() clear cached relationships even if the related id doesn't change.
-rw-r--r--django/db/models/base.py8
-rw-r--r--docs/ref/models/instances.txt7
-rw-r--r--tests/basic/tests.py12
3 files changed, 15 insertions, 12 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py
index f88690f225..8d4e19fa5a 100644
--- a/django/db/models/base.py
+++ b/django/db/models/base.py
@@ -609,13 +609,9 @@ class Model(metaclass=ModelBase):
# This field wasn't refreshed - skip ahead.
continue
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):
- rel_instance = field.get_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)
+ field.delete_cached_value(self)
# Clear cached relations.
for field in self._meta.related_objects:
diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt
index c327b0e9e7..73bbeb8f31 100644
--- a/docs/ref/models/instances.txt
+++ b/docs/ref/models/instances.txt
@@ -137,12 +137,7 @@ following is done:
1. All non-deferred fields of the model are updated to the values currently
present in the database.
-2. The previously loaded related instances for which the relation's value is no
- 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``.
+2. Any cached relations are cleared from the reloaded instance.
Only fields of the model are reloaded from the database. Other
database-dependent values such as annotations aren't reloaded. Any
diff --git a/tests/basic/tests.py b/tests/basic/tests.py
index 7a99ab0cf0..1a5e95e9d6 100644
--- a/tests/basic/tests.py
+++ b/tests/basic/tests.py
@@ -722,3 +722,15 @@ class ModelRefreshTests(TestCase):
FeaturedArticle.objects.create(article_id=article.pk)
article.refresh_from_db()
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')