summaryrefslogtreecommitdiff
path: root/django
diff options
context:
space:
mode:
authorAnssi Kääriäinen <akaariai@gmail.com>2013-08-30 09:41:07 +0300
committerAnssi Kääriäinen <akaariai@gmail.com>2013-08-30 09:41:07 +0300
commite973ee6a9879969b8ae05bb7ff681172cc5386a5 (patch)
treed144ae6297a03a3e9836f47c4cd4a08e51ad335d /django
parent13be3bfef1441f9f3c9eb3cad21b5ae158fdb874 (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.py18
-rw-r--r--django/db/models/options.py4
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