From c181734fa1ceab9d917a313a0567c9a71c2c4b0b Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Thu, 28 Aug 2008 17:18:05 +0000 Subject: [PATCH] Changed create() and get_or_create() to force an insert (not update an 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 --- django/db/models/query.py | 4 ++-- docs/ref/models/instances.txt | 2 ++ docs/ref/models/querysets.txt | 24 +++++++++++++++++++++--- 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/django/db/models/query.py b/django/db/models/query.py index c5e9cce90a..655f87a482 100644 --- a/django/db/models/query.py +++ b/django/db/models/query.py @@ -308,7 +308,7 @@ class QuerySet(object): 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 @@ class QuerySet(object): 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: diff --git a/docs/ref/models/instances.txt b/docs/ref/models/instances.txt index 404d473629..07509daa81 100644 --- a/docs/ref/models/instances.txt +++ b/docs/ref/models/instances.txt @@ -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 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index c0b3ac1de0..ffb9c4ba32 100644 --- a/docs/ref/models/querysets.txt +++ b/docs/ref/models/querysets.txt @@ -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 ` 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