mirror of https://github.com/django/django.git
Fixed #34925 -- Prevented Model.refresh_from_db() from mutating list of fields.
This commit is contained in:
parent
1c6e8ec4ed
commit
b0ec87b857
|
@ -691,7 +691,7 @@ class Model(AltersData, metaclass=ModelBase):
|
||||||
self._prefetched_objects_cache = {}
|
self._prefetched_objects_cache = {}
|
||||||
else:
|
else:
|
||||||
prefetched_objects_cache = getattr(self, "_prefetched_objects_cache", ())
|
prefetched_objects_cache = getattr(self, "_prefetched_objects_cache", ())
|
||||||
for field in fields:
|
for field in list(fields):
|
||||||
if field in prefetched_objects_cache:
|
if field in prefetched_objects_cache:
|
||||||
del prefetched_objects_cache[field]
|
del prefetched_objects_cache[field]
|
||||||
fields.remove(field)
|
fields.remove(field)
|
||||||
|
|
|
@ -38,6 +38,9 @@ class SelfRef(models.Model):
|
||||||
related_name="+",
|
related_name="+",
|
||||||
)
|
)
|
||||||
article = models.ForeignKey(Article, models.SET_NULL, null=True, blank=True)
|
article = models.ForeignKey(Article, models.SET_NULL, null=True, blank=True)
|
||||||
|
article_cited = models.ForeignKey(
|
||||||
|
Article, models.SET_NULL, null=True, blank=True, related_name="cited"
|
||||||
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
# This method intentionally doesn't work for all cases - part
|
# This method intentionally doesn't work for all cases - part
|
||||||
|
|
|
@ -926,24 +926,32 @@ class ModelRefreshTests(TestCase):
|
||||||
|
|
||||||
def test_prefetched_cache_cleared(self):
|
def test_prefetched_cache_cleared(self):
|
||||||
a = Article.objects.create(pub_date=datetime(2005, 7, 28))
|
a = Article.objects.create(pub_date=datetime(2005, 7, 28))
|
||||||
s = SelfRef.objects.create(article=a)
|
s = SelfRef.objects.create(article=a, article_cited=a)
|
||||||
# refresh_from_db() without fields=[...]
|
# refresh_from_db() without fields=[...]
|
||||||
a1_prefetched = Article.objects.prefetch_related("selfref_set").first()
|
a1_prefetched = Article.objects.prefetch_related("selfref_set", "cited").first()
|
||||||
self.assertCountEqual(a1_prefetched.selfref_set.all(), [s])
|
self.assertCountEqual(a1_prefetched.selfref_set.all(), [s])
|
||||||
|
self.assertCountEqual(a1_prefetched.cited.all(), [s])
|
||||||
s.article = None
|
s.article = None
|
||||||
|
s.article_cited = None
|
||||||
s.save()
|
s.save()
|
||||||
# Relation is cleared and prefetch cache is stale.
|
# Relation is cleared and prefetch cache is stale.
|
||||||
self.assertCountEqual(a1_prefetched.selfref_set.all(), [s])
|
self.assertCountEqual(a1_prefetched.selfref_set.all(), [s])
|
||||||
|
self.assertCountEqual(a1_prefetched.cited.all(), [s])
|
||||||
a1_prefetched.refresh_from_db()
|
a1_prefetched.refresh_from_db()
|
||||||
# Cache was cleared and new results are available.
|
# Cache was cleared and new results are available.
|
||||||
self.assertCountEqual(a1_prefetched.selfref_set.all(), [])
|
self.assertCountEqual(a1_prefetched.selfref_set.all(), [])
|
||||||
|
self.assertCountEqual(a1_prefetched.cited.all(), [])
|
||||||
# refresh_from_db() with fields=[...]
|
# refresh_from_db() with fields=[...]
|
||||||
a2_prefetched = Article.objects.prefetch_related("selfref_set").first()
|
a2_prefetched = Article.objects.prefetch_related("selfref_set", "cited").first()
|
||||||
self.assertCountEqual(a2_prefetched.selfref_set.all(), [])
|
self.assertCountEqual(a2_prefetched.selfref_set.all(), [])
|
||||||
|
self.assertCountEqual(a2_prefetched.cited.all(), [])
|
||||||
s.article = a
|
s.article = a
|
||||||
|
s.article_cited = a
|
||||||
s.save()
|
s.save()
|
||||||
# Relation is added and prefetch cache is stale.
|
# Relation is added and prefetch cache is stale.
|
||||||
self.assertCountEqual(a2_prefetched.selfref_set.all(), [])
|
self.assertCountEqual(a2_prefetched.selfref_set.all(), [])
|
||||||
a2_prefetched.refresh_from_db(fields=["selfref_set"])
|
self.assertCountEqual(a2_prefetched.cited.all(), [])
|
||||||
|
a2_prefetched.refresh_from_db(fields=["selfref_set", "cited"])
|
||||||
# Cache was cleared and new results are available.
|
# Cache was cleared and new results are available.
|
||||||
self.assertCountEqual(a2_prefetched.selfref_set.all(), [s])
|
self.assertCountEqual(a2_prefetched.selfref_set.all(), [s])
|
||||||
|
self.assertCountEqual(a2_prefetched.cited.all(), [s])
|
||||||
|
|
Loading…
Reference in New Issue