diff --git a/django/db/backends/__init__.py b/django/db/backends/__init__.py
index 01144eb..2e24f73 100644
|
a
|
b
|
class BaseDatabaseFeatures(object):
|
| 281 | 281 | allow_sliced_subqueries = True |
| 282 | 282 | |
| 283 | 283 | supports_joins = True |
| | 284 | distinguishes_insert_from_update = True |
| 284 | 285 | supports_select_related = True |
| 285 | 286 | |
| 286 | 287 | # Does the default test database allow multiple connections? |
diff --git a/django/db/models/base.py b/django/db/models/base.py
index 286f9b0..c0238b6 100644
|
a
|
b
|
class Model(object):
|
| 273 | 273 | _deferred = False |
| 274 | 274 | |
| 275 | 275 | def __init__(self, *args, **kwargs): |
| | 276 | self._entity_exists = kwargs.pop('__entity_exists', False) |
| 276 | 277 | signals.pre_init.send(sender=self.__class__, args=args, kwargs=kwargs) |
| 277 | 278 | |
| 278 | 279 | # Set up the storage for instance state |
| … |
… |
class Model(object):
|
| 362 | 363 | pass |
| 363 | 364 | if kwargs: |
| 364 | 365 | raise TypeError("'%s' is an invalid keyword argument for this function" % kwargs.keys()[0]) |
| | 366 | self._original_pk = self.pk if self._meta.pk is not None else None |
| 365 | 367 | super(Model, self).__init__() |
| 366 | 368 | signals.post_init.send(sender=self.__class__, instance=self) |
| 367 | 369 | |
| … |
… |
class Model(object):
|
| 470 | 472 | ('raw', 'cls', and 'origin'). |
| 471 | 473 | """ |
| 472 | 474 | using = using or router.db_for_write(self.__class__, instance=self) |
| | 475 | entity_exists = bool(self._entity_exists and self._original_pk == self.pk) |
| 473 | 476 | connection = connections[using] |
| 474 | 477 | assert not (force_insert and force_update) |
| 475 | 478 | if cls is None: |
| … |
… |
class Model(object):
|
| 516 | 519 | pk_set = pk_val is not None |
| 517 | 520 | record_exists = True |
| 518 | 521 | manager = cls._base_manager |
| 519 | | if pk_set: |
| | 522 | # TODO/NONREL: Some backends could emulate force_insert/_update |
| | 523 | # with an optimistic transaction, but since it's costly we should |
| | 524 | # only do it when the user explicitly wants it. |
| | 525 | # By adding support for an optimistic locking transaction |
| | 526 | # in Django (SQL: SELECT ... FOR UPDATE) we could even make that |
| | 527 | # part fully reusable on all backends (the current .exists() |
| | 528 | # check below isn't really safe if you have lots of concurrent |
| | 529 | # requests. BTW, and neither is QuerySet.get_or_create). |
| | 530 | try_update = connection.features.distinguishes_insert_from_update |
| | 531 | if not try_update: |
| | 532 | record_exists = False |
| | 533 | |
| | 534 | if try_update and pk_set: |
| 520 | 535 | # Determine whether a record with the primary key already exists. |
| 521 | 536 | if (force_update or (not force_insert and |
| 522 | 537 | manager.using(using).filter(pk=pk_val).exists())): |
| … |
… |
class Model(object):
|
| 536 | 551 | order_value = manager.using(using).filter(**{field.name: getattr(self, field.attname)}).count() |
| 537 | 552 | self._order = order_value |
| 538 | 553 | |
| | 554 | if connection.features.distinguishes_insert_from_update: |
| | 555 | add = True |
| | 556 | else: |
| | 557 | add = not entity_exists |
| | 558 | |
| 539 | 559 | if not pk_set: |
| 540 | 560 | if force_update: |
| 541 | 561 | raise ValueError("Cannot force an update in save() with no primary key.") |
| 542 | | values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True), connection=connection)) |
| | 562 | values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, add), connection=connection)) |
| 543 | 563 | for f in meta.local_fields if not isinstance(f, AutoField)] |
| 544 | 564 | else: |
| 545 | | values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True), connection=connection)) |
| | 565 | values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, add), connection=connection)) |
| 546 | 566 | for f in meta.local_fields] |
| 547 | 567 | |
| 548 | 568 | record_exists = False |
| … |
… |
class Model(object):
|
| 566 | 586 | |
| 567 | 587 | # Signal that the save is complete |
| 568 | 588 | if origin and not meta.auto_created: |
| | 589 | if connection.features.distinguishes_insert_from_update: |
| | 590 | created = not record_exists |
| | 591 | else: |
| | 592 | created = not entity_exists |
| 569 | 593 | signals.post_save.send(sender=origin, instance=self, |
| 570 | | created=(not record_exists), raw=raw, using=using) |
| | 594 | created=created, raw=raw, using=using) |
| | 595 | |
| | 596 | self._entity_exists = True |
| | 597 | self._original_pk = self.pk |
| 571 | 598 | |
| 572 | 599 | |
| 573 | 600 | save_base.alters_data = True |
| … |
… |
class Model(object):
|
| 580 | 607 | collector.collect([self]) |
| 581 | 608 | collector.delete() |
| 582 | 609 | |
| | 610 | self._entity_exists = False |
| | 611 | self._original_pk = None |
| | 612 | |
| 583 | 613 | delete.alters_data = True |
| 584 | 614 | |
| 585 | 615 | def _get_FIELD_display(self, field): |
diff --git a/django/db/models/query.py b/django/db/models/query.py
index 26402ba..7a9bb45 100644
|
a
|
b
|
class QuerySet(object):
|
| 282 | 282 | if skip: |
| 283 | 283 | row_data = row[index_start:aggregate_start] |
| 284 | 284 | pk_val = row_data[pk_idx] |
| 285 | | obj = model_cls(**dict(zip(init_list, row_data))) |
| | 285 | obj = model_cls(**dict(zip(init_list, row_data), __entity_exists=True)) |
| 286 | 286 | else: |
| 287 | 287 | # Omit aggregates in object creation. |
| 288 | | obj = model(*row[index_start:aggregate_start]) |
| | 288 | obj = model(*row[index_start:aggregate_start], **{'__entity_exists': True}) |
| 289 | 289 | |
| 290 | 290 | # Store the source database of the object |
| 291 | 291 | obj._state.db = db |
| … |
… |
def get_cached_row(klass, row, index_start, using, max_depth=0, cur_depth=0,
|
| 1197 | 1197 | obj = None |
| 1198 | 1198 | elif skip: |
| 1199 | 1199 | klass = deferred_class_factory(klass, skip) |
| 1200 | | obj = klass(**dict(zip(init_list, fields))) |
| | 1200 | obj = klass(__entity_exists=True, **dict(zip(init_list, fields))) |
| 1201 | 1201 | else: |
| 1202 | | obj = klass(*fields) |
| | 1202 | obj = klass(*fields, **{'__entity_exists': True}) |
| 1203 | 1203 | |
| 1204 | 1204 | else: |
| 1205 | 1205 | # Load all fields on klass |
| … |
… |
def get_cached_row(klass, row, index_start, using, max_depth=0, cur_depth=0,
|
| 1215 | 1215 | if fields == (None,) * field_count: |
| 1216 | 1216 | obj = None |
| 1217 | 1217 | else: |
| 1218 | | obj = klass(**dict(zip(field_names, fields))) |
| | 1218 | obj = klass(__entity_exists=True, **dict(zip(field_names, fields))) |
| 1219 | 1219 | |
| 1220 | 1220 | # If an object was retrieved, set the database state. |
| 1221 | 1221 | if obj: |