4102_Django1.3_JL20110610.patch
|
|
|
278 | 278 | def __init__(self, *args, **kwargs): |
279 | 279 | signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs) |
280 | 280 | |
| 281 | self._reset_modified_attrs() |
| 282 | |
281 | 283 | # Set up the storage for instance state |
282 | 284 | self._state = ModelState() |
283 | 285 | |
… |
… |
|
368 | 370 | super(Model, self).__init__() |
369 | 371 | signals.post_init.send(sender=self.__class__, instance=self) |
370 | 372 | |
| 373 | def __setattr__(self, name, value): |
| 374 | if name not in self.__dict__.setdefault('_modified_attrs', []): |
| 375 | if not hasattr(self, name) or value != getattr(self, name): |
| 376 | self._modified_attrs.append(name) |
| 377 | super(Model, self).__setattr__(name, value) |
| 378 | |
| 379 | def _reset_modified_attrs(self): |
| 380 | self.__dict__['_modified_attrs'] = [] |
| 381 | |
371 | 382 | def __repr__(self): |
372 | 383 | try: |
373 | 384 | u = unicode(self) |
… |
… |
|
465 | 476 | save.alters_data = True |
466 | 477 | |
467 | 478 | def save_base(self, raw=False, cls=None, origin=None, force_insert=False, |
468 | | force_update=False, using=None): |
| 479 | force_update=False, using=None, modified_attrs=None): |
469 | 480 | """ |
470 | 481 | Does the heavy-lifting involved in saving. Subclasses shouldn't need to |
471 | 482 | override this method. It's separate from save() in order to hide the |
… |
… |
|
486 | 497 | if origin and not meta.auto_created: |
487 | 498 | signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using) |
488 | 499 | |
| 500 | if modified_attrs is None: |
| 501 | modified_attrs = self._modified_attrs |
| 502 | |
489 | 503 | # If we are in a raw save, save the object exactly as presented. |
490 | 504 | # That means that we don't try to be smart about saving attributes |
491 | 505 | # that might have come from the parent class - we just save the |
… |
… |
|
504 | 518 | if field and getattr(self, parent._meta.pk.attname) is None and getattr(self, field.attname) is not None: |
505 | 519 | setattr(self, parent._meta.pk.attname, getattr(self, field.attname)) |
506 | 520 | |
507 | | self.save_base(cls=parent, origin=org, using=using) |
| 521 | self.save_base(cls=parent, origin=org, using=using, modified_attrs=modified_attrs) |
508 | 522 | |
509 | 523 | if field: |
510 | 524 | setattr(self, field.attname, self._get_pk_val(parent._meta)) |
… |
… |
|
526 | 540 | # It does already exist, so do an UPDATE. |
527 | 541 | if force_update or non_pks: |
528 | 542 | values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks] |
| 543 | |
| 544 | # Only keep modified_attrs and those whose value has changed after pre_save |
| 545 | if self._state.db == using: |
| 546 | values = [v for v in values |
| 547 | if v[0].name in modified_attrs |
| 548 | or v[0].attname in modified_attrs |
| 549 | or v[2] != getattr(self, v[0].name)] |
529 | 550 | rows = manager.using(using).filter(pk=pk_val)._update(values) |
530 | 551 | if force_update and not rows: |
531 | 552 | raise DatabaseError("Forced update did not affect any rows.") |
… |
… |
|
562 | 583 | setattr(self, meta.pk.attname, result) |
563 | 584 | transaction.commit_unless_managed(using=using) |
564 | 585 | |
| 586 | self._reset_modified_attrs() |
| 587 | |
565 | 588 | # Store the database on which the object was saved |
566 | 589 | self._state.db = using |
567 | 590 | # Once saved, this is no longer a to-be-added instance. |