Ticket #4102: 4102-r16288.diff
File 4102-r16288.diff, 5.2 KB (added by , 13 years ago) |
---|
-
django/db/models/base.py
diff --git a/django/db/models/base.py b/django/db/models/base.py
a b 276 276 _deferred = False 277 277 278 278 def __init__(self, *args, **kwargs): 279 self._reset_modified_attrs() 279 280 signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs) 280 281 281 282 # Set up the storage for instance state 282 283 self._state = ModelState() 283 284 284 285 # There is a rather weird disparity here; if kwargs, it's set, then args 285 # overrides it. It should be one or the other; don't duplicate the work 286 # overrides it. It should be one or the other; don't duplicate the work. 286 287 # The reason for the kwargs check is that standard iterator passes in by 287 288 # args, and instantiation for iteration is 33% faster. 288 289 args_len = len(args) … … 368 369 super(Model, self).__init__() 369 370 signals.post_init.send(sender=self.__class__, instance=self) 370 371 372 def __setattr__(self, name, value): 373 if name not in self._modified_attrs: 374 if not hasattr(self, name) or value != getattr(self, name): 375 self._modified_attrs.append(name) 376 super(Model, self).__setattr__(name, value) 377 378 def _reset_modified_attrs(self): 379 self.__dict__['_modified_attrs'] = [] 380 371 381 def __repr__(self): 372 382 try: 373 383 u = unicode(self) … … 514 524 if not meta.proxy: 515 525 non_pks = [f for f in meta.local_fields if not f.primary_key] 516 526 527 if self._state.db == using: 528 modified_attrs = self._modified_attrs 529 non_pks = [f for f in non_pks if (f.name in modified_attrs or f.attname in modified_attrs)] 530 self._reset_modified_attrs() 531 517 532 # First, try an UPDATE. If that doesn't update anything, do an INSERT. 518 533 pk_val = self._get_pk_val(meta) 519 534 pk_set = pk_val is not None -
django/db/models/query.py
diff --git a/django/db/models/query.py b/django/db/models/query.py
a b 284 284 else: 285 285 # Omit aggregates in object creation. 286 286 obj = model(*row[index_start:aggregate_start]) 287 # Models keep a track of modified attrs to choose which 288 # fields to save. Since we're just pulling from the 289 # database, nothing has changed yet. 290 obj._reset_modified_attrs() 287 291 288 292 # Store the source database of the object 289 293 obj._state.db = db -
new file tests/regressiontests/update_fields/models.py
diff --git a/tests/regressiontests/update_fields/__init__.py b/tests/regressiontests/update_fields/__init__.py new file mode 100644 diff --git a/tests/regressiontests/update_fields/models.py b/tests/regressiontests/update_fields/models.py new file mode 100644
- + 1 """ 2 Save only modified fields on update 3 """ 4 from django.db import models 5 6 class Article(models.Model): 7 headline = models.CharField(max_length=100, default='Default headline') 8 body = models.TextField() 9 pub_date = models.DateTimeField() 10 11 class Meta: 12 ordering = ('pub_date','headline') 13 14 def __str__(self): 15 return self.headline -
new file tests/regressiontests/update_fields/tests.py
diff --git a/tests/regressiontests/update_fields/tests.py b/tests/regressiontests/update_fields/tests.py new file mode 100644
- + 1 from datetime import datetime 2 3 from django.test import TestCase 4 5 from models import Article 6 7 8 class UpdateFieldsTest(TestCase): 9 10 def test_basic_update_fields(self): 11 # Create a couple of Articles. 12 a = Article(headline=u'Article 1', body=u'Body 1', pub_date=datetime(2007, 5, 5)) 13 a.save() 14 15 # Change headline and body on different instances, then save both to 16 # verify that each only updated the modified field. 17 a1 = Article.objects.get(pk=a.id) 18 a2 = Article.objects.get(pk=a.id) 19 a1.headline = u'Changed article 1' 20 a2.body = u'Changed body 1' 21 a1.save() 22 a2.save() 23 a3 = Article.objects.get(pk=a.id) 24 self.assertEqual(a3.headline, u'Changed article 1') 25 self.assertEqual(a3.body, u'Changed body 1') 26 27 # Fields entered at instantiation of a model which will already exists 28 # should be saved as well. 29 a = Article(id=a.id, headline=u'Reset article 1', body=u'Reset body 1', pub_date=datetime(2007, 5, 5)) 30 a.save() 31 a3 = Article.objects.get(pk=a.id) 32 self.assertEqual(a3.headline, u'Reset article 1') 33 self.assertEqual(a3.body, u'Reset body 1') 34 35 # If the value doesn't change, it won't be marked as modified -- 36 # otherwise user input like forms/etc is going to mark everything 37 # modified regardless. 38 a1 = Article.objects.get(pk=a.id) 39 a2 = Article.objects.get(pk=a.id) 40 a1.headline = u'Changed article 2' 41 a2.headline = a2.headline 42 a2.body = u'Changed body 2' 43 a1.save() 44 a2.save() 45 a3 = Article.objects.get(pk=a.id) 46 self.assertEqual(a3.headline, u'Changed article 2') 47 self.assertEqual(a3.body, u'Changed body 2')