Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Changed create() and get_or_create() to force an insert (not update a…

…n existing value).

Backwards incompatible if you are using manually-specific primary key values
and relying on the previously documented behaviour that the new values would
always exist in the database (i.e. it would update the existing entry).

Fixed #8419.


git-svn-id: http://code.djangoproject.com/svn/django/trunk@8670 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
commit c181734fa1ceab9d917a313a0567c9a71c2c4b0b 1 parent 79348d4
Malcolm Tredinnick malcolmt authored
4 django/db/models/query.py
View
@@ -308,7 +308,7 @@ def create(self, **kwargs):
and returning the created object.
"""
obj = self.model(**kwargs)
- obj.save()
+ obj.save(force_insert=True)
return obj
def get_or_create(self, **kwargs):
@@ -328,7 +328,7 @@ def get_or_create(self, **kwargs):
params.update(defaults)
obj = self.model(**params)
sid = transaction.savepoint()
- obj.save()
+ obj.save(force_insert=True)
transaction.savepoint_commit(sid)
return obj, True
except IntegrityError, e:
2  docs/ref/models/instances.txt
View
@@ -193,6 +193,8 @@ 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.
+.. _ref-models-force-insert:
+
Forcing an INSERT or UPDATE
~~~~~~~~~~~~~~~~~~~~~~~~~~~
24 docs/ref/models/querysets.txt
View
@@ -556,10 +556,18 @@ A convenience method for creating an object and saving it all in one step. Thus
and::
p = Person(first_name="Bruce", last_name="Springsteen")
- p.save()
+ p.save(force_insert=True)
are equivalent.
+The :ref:`force_insert <ref-models-force-insert>` parameter is documented
+elsewhere, but all it means is that a new object will always be created.
+Normally you won't need to worry about this. However, if your model contains a
+manual primary key value that you set and if that value already exists in the
+database, a call to ``create()`` will fail with an ``IntegrityError`` since
+primary keys must be unique. So remember to be prepared to handle the
+exception if you are using manual primary keys.
+
``get_or_create(**kwargs)``
~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -590,7 +598,7 @@ called ``defaults`` -- will be used in a ``get()`` call. If an object is found,
``get_or_create()`` returns a tuple of that object and ``False``. If an object
is *not* found, ``get_or_create()`` will instantiate and save a new object,
returning a tuple of the new object and ``True``. The new object will be
-created according to this algorithm::
+created roughly according to this algorithm::
defaults = kwargs.pop('defaults', {})
params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
@@ -601,13 +609,23 @@ created according to this algorithm::
In English, that means start with any non-``'defaults'`` keyword argument that
doesn't contain a double underscore (which would indicate a non-exact lookup).
Then add the contents of ``defaults``, overriding any keys if necessary, and
-use the result as the keyword arguments to the model class.
+use the result as the keyword arguments to the model class. As hinted at
+above, this is a simplification of the algorithm that is used, but it contains
+all the pertinent details. The internal implementation has some more
+error-checking than this and handles some extra edge-conditions; if you're
+interested, read the code.
If you have a field named ``defaults`` and want to use it as an exact lookup in
``get_or_create()``, just use ``'defaults__exact'``, like so::
Foo.objects.get_or_create(defaults__exact='bar', defaults={'defaults': 'baz'})
+
+The ``get_or_create()`` method has similar error behaviour to ``create()``
+when you are using manually specified primary keys. If an object needs to be
+created and the key already exists in the database, an ``IntegrityError`` will
+be raised.
+
Finally, a word on using ``get_or_create()`` in Django views. As mentioned
earlier, ``get_or_create()`` is mostly useful in scripts that need to parse
data and create new records if existing ones aren't available. But if you need
Please sign in to comment.
Something went wrong with that request. Please try again.