From 45a650777e4674bc540c3bf4b3108409f0e1f98a Mon Sep 17 00:00:00 2001 From: Tim Graham Date: Tue, 21 Jun 2016 13:46:22 -0400 Subject: [PATCH] [1.10.x] Fixed #26787 -- Documented deleting and reloading of model instance fields. Thanks Julien Hartmann for the report. Backport of 20d1cb33c2ec1242e16c49deb88e8c70517b2d1a from master --- docs/ref/models/instances.txt | 12 ++++++++++++ docs/releases/1.10.txt | 3 +++ tests/basic/tests.py | 13 +++++++++++++ 3 files changed, 28 insertions(+) diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt index 517c29e867d..101e1d94a05 100644 --- a/docs/ref/models/instances.txt +++ b/docs/ref/models/instances.txt @@ -128,6 +128,18 @@ in the ``from_db()`` method. Refreshing objects from database ================================ +If you delete a field from a model instance, accessing it again reloads the +value from the database:: + + >>> obj = MyModel.objects.first() + >>> del obj.field + >>> obj.field # Loads the field from the database + +.. versionchanged:: 1.10 + + In older versions, accessing a deleted field raised ``AttributeError`` + instead of reloading it. + .. method:: Model.refresh_from_db(using=None, fields=None) If you need to reload a model's values from the database, you can use the diff --git a/docs/releases/1.10.txt b/docs/releases/1.10.txt index 8dd97e3da8a..752684e3fae 100644 --- a/docs/releases/1.10.txt +++ b/docs/releases/1.10.txt @@ -884,6 +884,9 @@ Miscellaneous * The ``_base_manager`` and ``_default_manager`` attributes are removed from model instances. They remain accessible on the model class. +* Accessing a deleted field on a model instance, e.g. after ``del obj.field``, + reloads the field's value instead of raising ``AttributeError``. + .. _deprecated-features-1.10: Features deprecated in 1.10 diff --git a/tests/basic/tests.py b/tests/basic/tests.py index 56b778c4192..16c9dd9dae0 100644 --- a/tests/basic/tests.py +++ b/tests/basic/tests.py @@ -421,6 +421,19 @@ class ModelTest(TestCase): # hash) hash(Article()) + def test_delete_and_access_field(self): + # Accessing a field after it's deleted from a model reloads its value. + pub_date = datetime.now() + article = Article.objects.create(headline='foo', pub_date=pub_date) + new_pub_date = article.pub_date + timedelta(days=10) + article.headline = 'bar' + article.pub_date = new_pub_date + del article.headline + with self.assertNumQueries(1): + self.assertEqual(article.headline, 'foo') + # Fields that weren't deleted aren't reloaded. + self.assertEqual(article.pub_date, new_pub_date) + class ModelLookupTest(TestCase): def setUp(self):