Ticket #4102: 4102_Django1.3_JL20110610.patch
File 4102_Django1.3_JL20110610.patch, 6.5 KB (added by , 13 years ago) |
---|
-
django/db/models/base.py
diff -rupN a//django/db/models/base.py b//django/db/models/base.py
a b class Model(object): 275 275 def __init__(self, *args, **kwargs): 276 276 signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs) 277 277 278 self._reset_modified_attrs() 279 278 280 # Set up the storage for instance state 279 281 self._state = ModelState() 280 282 281 283 # There is a rather weird disparity here; if kwargs, it's set, then args 282 # overrides it. It should be one or the other; don't duplicate the work 284 # overrides it. It should be one or the other; don't duplicate the work. 283 285 # The reason for the kwargs check is that standard iterator passes in by 284 286 # args, and instantiation for iteration is 33% faster. 285 287 args_len = len(args) … … class Model(object): 365 367 super(Model, self).__init__() 366 368 signals.post_init.send(sender=self.__class__, instance=self) 367 369 370 def __setattr__(self, name, value): 371 if name not in self.__dict__.setdefault('_modified_attrs', []): 372 if not hasattr(self, name) or value != getattr(self, name): 373 self._modified_attrs.append(name) 374 super(Model, self).__setattr__(name, value) 375 376 def _reset_modified_attrs(self): 377 self.__dict__['_modified_attrs'] = [] 378 368 379 def __repr__(self): 369 380 try: 370 381 u = unicode(self) … … class Model(object): 523 534 # It does already exist, so do an UPDATE. 524 535 if force_update or non_pks: 525 536 values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks] 537 538 # Only keep modified_attrs and those whose value has changed after pre_save 539 if self._state.db == using: 540 modified_attrs = self._modified_attrs 541 values = [v for v in values 542 if v[0].name in modified_attrs or v[0].attname in modified_attrs or 543 v[2] != getattr(self, v[0].name)] 526 544 rows = manager.using(using).filter(pk=pk_val)._update(values) 527 545 if force_update and not rows: 528 546 raise DatabaseError("Forced update did not affect any rows.") … … class Model(object): 559 577 setattr(self, meta.pk.attname, result) 560 578 transaction.commit_unless_managed(using=using) 561 579 580 self._reset_modified_attrs() 581 562 582 # Store the database on which the object was saved 563 583 self._state.db = using 564 584 # Once saved, this is no longer a to-be-added instance. -
django/db/models/query.py
diff -rupN a//django/db/models/query.py b//django/db/models/query.py
a b class QuerySet(object): 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 -
tests/regressiontests/update_fields/models.py
diff -rupN a//tests/regressiontests/update_fields/models.py b//tests/regressiontests/update_fields/models.py
a b 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 modify_date = models.DateTimeField(auto_now=True) 11 12 class Meta: 13 ordering = ('pub_date','headline') 14 15 def __str__(self): 16 return self.headline -
tests/regressiontests/update_fields/tests.py
diff -rupN a//tests/regressiontests/update_fields/tests.py b//tests/regressiontests/update_fields/tests.py
a b 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 24 # The pre_save method should change the new modify_date of a1 and a2 25 self.assertNotEqual(a1.modify_date, a2.modify_date) 26 27 a3 = Article.objects.get(pk=a.id) 28 self.assertEqual(a3.headline, u'Changed article 1') 29 self.assertEqual(a3.body, u'Changed body 1') 30 self.assertEqual(a3.modify_date, a2.modify_date) 31 32 # Fields entered at instantiation of a model which will already exists 33 # should be saved as well. 34 a = Article(id=a.id, headline=u'Reset article 1', body=u'Reset body 1', pub_date=datetime(2007, 5, 5)) 35 a.save() 36 a3 = Article.objects.get(pk=a.id) 37 self.assertEqual(a3.headline, u'Reset article 1') 38 self.assertEqual(a3.body, u'Reset body 1') 39 40 # If the value doesn't change, it won't be marked as modified -- 41 # otherwise user input like forms/etc is going to mark everything 42 # modified regardless. 43 a1 = Article.objects.get(pk=a.id) 44 a2 = Article.objects.get(pk=a.id) 45 a1.headline = u'Changed article 2' 46 a2.headline = a2.headline 47 a2.body = u'Changed body 2' 48 a1.save() 49 a2.save() 50 a3 = Article.objects.get(pk=a.id) 51 self.assertEqual(a3.headline, u'Changed article 2') 52 self.assertEqual(a3.body, u'Changed body 2')