diff options
| author | Anssi Kääriäinen <akaariai@gmail.com> | 2013-08-30 09:41:07 +0300 |
|---|---|---|
| committer | Anssi Kääriäinen <akaariai@gmail.com> | 2013-08-30 09:41:07 +0300 |
| commit | e973ee6a9879969b8ae05bb7ff681172cc5386a5 (patch) | |
| tree | d144ae6297a03a3e9836f47c4cd4a08e51ad335d /django | |
| parent | 13be3bfef1441f9f3c9eb3cad21b5ae158fdb874 (diff) | |
Fixed #20988 -- Added model meta option select_on_save
The option can be used to force pre 1.6 style SELECT on save behaviour.
This is needed in case the database returns zero updated rows even if
there is a matching row in the DB. One such case is PostgreSQL update
trigger that returns NULL.
Reviewed by Tim Graham.
Refs #16649
Diffstat (limited to 'django')
| -rw-r--r-- | django/db/models/base.py | 18 | ||||
| -rw-r--r-- | django/db/models/options.py | 4 |
2 files changed, 16 insertions, 6 deletions
diff --git a/django/db/models/base.py b/django/db/models/base.py index d63017c438..887381187d 100644 --- a/django/db/models/base.py +++ b/django/db/models/base.py @@ -667,7 +667,9 @@ class Model(six.with_metaclass(ModelBase)): base_qs = cls._base_manager.using(using) values = [(f, None, (getattr(self, f.attname) if raw else f.pre_save(self, False))) for f in non_pks] - updated = self._do_update(base_qs, using, pk_val, values, update_fields) + forced_update = update_fields or force_update + updated = self._do_update(base_qs, using, pk_val, values, update_fields, + forced_update) if force_update and not updated: raise DatabaseError("Forced update did not affect any rows.") if update_fields and not updated: @@ -691,21 +693,27 @@ class Model(six.with_metaclass(ModelBase)): setattr(self, meta.pk.attname, result) return updated - def _do_update(self, base_qs, using, pk_val, values, update_fields): + def _do_update(self, base_qs, using, pk_val, values, update_fields, forced_update): """ This method will try to update the model. If the model was updated (in the sense that an update query was done and a matching row was found from the DB) the method will return True. """ + filtered = base_qs.filter(pk=pk_val) if not values: # We can end up here when saving a model in inheritance chain where # update_fields doesn't target any field in current model. In that # case we just say the update succeeded. Another case ending up here # is a model with just PK - in that case check that the PK still # exists. - return update_fields is not None or base_qs.filter(pk=pk_val).exists() - else: - return base_qs.filter(pk=pk_val)._update(values) > 0 + return update_fields is not None or filtered.exists() + if self._meta.select_on_save and not forced_update: + if filtered.exists(): + filtered._update(values) + return True + else: + return False + return filtered._update(values) > 0 def _do_insert(self, manager, using, fields, update_pk, raw): """ diff --git a/django/db/models/options.py b/django/db/models/options.py index 14f73c301f..5221468493 100644 --- a/django/db/models/options.py +++ b/django/db/models/options.py @@ -22,7 +22,8 @@ DEFAULT_NAMES = ('verbose_name', 'verbose_name_plural', 'db_table', 'ordering', 'unique_together', 'permissions', 'get_latest_by', 'order_with_respect_to', 'app_label', 'db_tablespace', 'abstract', 'managed', 'proxy', 'swappable', 'auto_created', - 'index_together', 'app_cache', 'default_permissions') + 'index_together', 'app_cache', 'default_permissions', + 'select_on_save') @python_2_unicode_compatible class Options(object): @@ -35,6 +36,7 @@ class Options(object): self.ordering = [] self.unique_together = [] self.index_together = [] + self.select_on_save = False self.default_permissions = ('add', 'change', 'delete') self.permissions = [] self.object_name, self.app_label = None, app_label |
