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
This commit is contained in:
Anssi Kääriäinen 2013-08-30 09:41:07 +03:00
parent 13be3bfef1
commit e973ee6a98
7 changed files with 130 additions and 16 deletions

View file

@ -305,16 +305,23 @@ follows this algorithm:
* If the object's primary key attribute is *not* set or if the ``UPDATE``
didn't update anything, Django executes an ``INSERT``.
.. versionchanged:: 1.6
Previously Django used ``SELECT`` - if not found ``INSERT`` else ``UPDATE``
algorithm. The old algorithm resulted in one more query in ``UPDATE`` case.
The one gotcha here is that you should be careful not to specify a primary-key
value explicitly when saving new objects, if you cannot guarantee the
primary-key value is unused. For more on this nuance, see `Explicitly specifying
auto-primary-key values`_ above and `Forcing an INSERT or UPDATE`_ below.
.. versionchanged:: 1.6
Previously Django did a ``SELECT`` when the primary key attribute was set.
If the ``SELECT`` found a row, then Django did an ``UPDATE``, otherwise it
did an ``INSERT``. The old algorithm results in one more query in the
``UPDATE`` case. There are some rare cases where the database doesn't
report that a row was updated even if the database contains a row for the
object's primary key value. An example is the PostgreSQL ``ON UPDATE``
trigger which returns ``NULL``. In such cases it is possible to revert to the
old algorithm by setting the :attr:`~django.db.models.Options.select_on_save`
option to ``True``.
.. _ref-models-force-insert:
Forcing an INSERT or UPDATE

View file

@ -256,6 +256,28 @@ Django quotes column and table names behind the scenes.
If ``proxy = True``, a model which subclasses another model will be treated as
a :ref:`proxy model <proxy-models>`.
``select_on_save``
------------------
.. attribute:: Options.select_on_save
.. versionadded:: 1.6
Determines if Django will use the pre-1.6
:meth:`django.db.models.Model.save()` algorithm. The old algorithm
uses ``SELECT`` to determine if there is an existing row to be updated.
The new algorith tries an ``UPDATE`` directly. In some rare cases the
``UPDATE`` of an existing row isn't visible to Django. An example is the
PostgreSQL ``ON UPDATE`` trigger which returns ``NULL``. In such cases the
new algorithm will end up doing an ``INSERT`` even when a row exists in
the database.
Usually there is no need to set this attribute. The default is
``False``.
See :meth:`django.db.models.Model.save()` for more about the old and
new saving algorithm.
``unique_together``
-------------------