Fixed #12579 -- Noted QuerySet.get_or_create() depends on database unique constraints.

Thanks timmolendijk, jdunck, vijay_shanker, and loic84.
This commit is contained in:
Tim Graham 2013-07-03 07:59:35 -04:00
parent 231e31c690
commit 428de2e339
1 changed files with 21 additions and 10 deletions

View File

@ -1334,7 +1334,7 @@ get_or_create
.. method:: get_or_create(**kwargs) .. method:: get_or_create(**kwargs)
A convenience method for looking up an object with the given kwargs (may be A convenience method for looking up an object with the given ``kwargs`` (may be
empty if your model has defaults for all fields), creating one if necessary. empty if your model has defaults for all fields), creating one if necessary.
.. versionchanged:: 1.6 .. versionchanged:: 1.6
@ -1345,8 +1345,7 @@ Returns a tuple of ``(object, created)``, where ``object`` is the retrieved or
created object and ``created`` is a boolean specifying whether a new object was created object and ``created`` is a boolean specifying whether a new object was
created. created.
This is meant as a shortcut to boilerplatish code and is mostly useful for This is meant as a shortcut to boilerplatish code. For example::
data-import scripts. For example::
try: try:
obj = Person.objects.get(first_name='John', last_name='Lennon') obj = Person.objects.get(first_name='John', last_name='Lennon')
@ -1394,13 +1393,25 @@ when you're using manually specified primary keys. If an object needs to be
created and the key already exists in the database, an created and the key already exists in the database, an
:exc:`~django.db.IntegrityError` will be raised. :exc:`~django.db.IntegrityError` will be raised.
Finally, a word on using ``get_or_create()`` in Django views. As mentioned This method is atomic assuming correct usage, correct database configuration,
earlier, ``get_or_create()`` is mostly useful in scripts that need to parse and correct behavior of the underlying database. However, if uniqueness is not
data and create new records if existing ones aren't available. But if you need enforced at the database level for the ``kwargs`` used in a ``get_or_create``
to use ``get_or_create()`` in a view, please make sure to use it only in call (see :attr:`~django.db.models.Field.unique` or
``POST`` requests unless you have a good reason not to. ``GET`` requests :attr:`~django.db.models.Options.unique_together`), this method is prone to a
shouldn't have any effect on data; use ``POST`` whenever a request to a page race-condition which can result in multiple rows with the same parameters being
has a side effect on your data. For more, see `Safe methods`_ in the HTTP spec. inserted simultaneously.
If you are using MySQL, be sure to use the ``READ COMMITTED`` isolation level
rather than ``REPEATABLE READ`` (the default), otherwise you may see cases
where ``get_or_create`` will raise an :exc:`~django.db.IntegrityError` but the
object won't appear in a subsequent :meth:`~django.db.models.query.QuerySet.get`
call.
Finally, a word on using ``get_or_create()`` in Django views: please make sure
to use it only in ``POST`` requests unless you have a good reason not to
``GET`` requests shouldn't have any effect on data; use ``POST`` whenever a
request to a page as a side effect on your data. For more, see `Safe methods`_
in the HTTP spec.
.. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 .. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1