Ticket #3182: 3182.update_or_create-only.3.diff
File 3182.update_or_create-only.3.diff, 8.4 KB (added by , 12 years ago) |
---|
-
django/db/models/manager.py
diff --git a/django/db/models/manager.py b/django/db/models/manager.py index e1bbf6e..c32b45e 100644
a b class Manager(object): 133 133 def get_or_create(self, **kwargs): 134 134 return self.get_query_set().get_or_create(**kwargs) 135 135 136 def update_or_create(self, **kwargs): 137 return self.get_query_set().update_or_create(**kwargs) 138 136 139 def create(self, **kwargs): 137 140 return self.get_query_set().create(**kwargs) 138 141 -
django/db/models/query.py
diff --git a/django/db/models/query.py b/django/db/models/query.py index 755820c..1c2dad5 100644
a b class QuerySet(object): 469 469 # Re-raise the IntegrityError with its original traceback. 470 470 raise exc_info[1], None, exc_info[2] 471 471 472 def update_or_create(self, **kwargs): 473 """ 474 Looks up an object with the given kwargs, creating one if necessary. 475 If the object already exists, then its fields are updated with the 476 values passed in the defaults dictionary. 477 Returns a tuple of (object, created), where created is a boolean 478 specifying whether an object was created. 479 480 TODO: opportunity for refactoring common code with get_or_create() 481 """ 482 assert kwargs, \ 483 'update_or_create() must be passed at least one keyword argument' 484 defaults = kwargs.pop('defaults', {}) 485 lookup = kwargs.copy() 486 for f in self.model._meta.fields: 487 if f.attname in lookup: 488 lookup[f.name] = lookup.pop(f.attname) 489 self._for_write = True 490 sid = transaction.savepoint(using=self.db) 491 try: 492 obj = self.get(**lookup) 493 create = False 494 except self.model.DoesNotExist: 495 params = dict([(k, v) for k, v in kwargs.items() if '__' not in k]) 496 obj = self.model(**params) 497 create = True 498 for attname, value in defaults.items(): 499 setattr(obj, attname, value) 500 try: 501 obj.save(force_insert=create, using=self.db) 502 transaction.savepoint_commit(sid, using=self.db) 503 return obj, create 504 except IntegrityError: 505 transaction.savepoint_rollback(sid, using=self.db) 506 exc_info = sys.exc_info() 507 raise exc_info[1], None, exc_info[2] 508 472 509 def latest(self, field_name=None): 473 510 """ 474 511 Returns the latest object, according to the model's 'get_latest_by' -
docs/ref/models/querysets.txt
diff --git a/docs/ref/models/querysets.txt b/docs/ref/models/querysets.txt index eef2272..dfe04a0 100644
a b has a side effect on your data. For more, see `Safe methods`_ in the HTTP spec. 1342 1342 1343 1343 .. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 1344 1344 1345 update_or_create 1346 ~~~~~~~~~~~~~~~~ 1347 1348 .. method:: update_or_create(**kwargs) 1349 1350 .. versionadded:: 1.5 1351 1352 A convenience method for looking up an object with the given kwargs, and then 1353 either updating the values of the object if one is found or creating an 1354 object if one was not found. 1355 1356 Like ``get_or_create()``, this method returns a tuple of ``(object, created)``, 1357 where ``object`` is the updated or created object and ``created`` is a boolean 1358 specifying whether a new object was created. 1359 1360 This is meant as a shortcut to the following type of code:: 1361 1362 obj, created = Person.objects.get_or_create(first_name='John', last_name='Lennon', 1363 defaults={'birthday': date(1940, 10, 9)}) 1364 if not created: 1365 obj.update(birthday=date(1940, 10, 9)) 1366 1367 This pattern gets quite unwieldy as the number of fields in a model goes up. 1368 The above example can be rewritten using ``update_or_create()`` like so:: 1369 1370 obj, created = Person.objects.update_or_create(first_name='John', last_name='Lennon', 1371 defaults={'birthday': date(1940, 10, 9)}) 1372 1373 Any keyword arguments passed to ``update_or_create()`` — *except* an optional 1374 one called ``defaults`` — will be used in a :meth:`get()` call. If an object is 1375 found, ``update_or_create()`` updates values of its fields according to 1376 ``defaults`` and returns a tuple of that object and ``False``. If an object is 1377 *not* found, ``update_or_create()`` will instantiate and save a new object, 1378 returning a tuple of the new object and ``True``. The new object will be created 1379 in a similar way to ``get_or_create()``. 1380 1381 The ``defaults`` parameter should be a dict of attribute-value pairs that 1382 you want to update. If ``defaults`` is empty or not specified, then 1383 ``update_or_create()`` will act exactly like ``get_or_create()`` since there 1384 would be nothing to update. 1385 1386 As with ``get_or_create()``, if you need to use ``update_or_create()`` in a 1387 view, please make sure to use it only in ``POST`` requests unless you have a 1388 good reason not to. ``GET`` requests shouldn't have any effect on data; use 1389 ``POST`` whenever a request to a page has a side effect on your data. For 1390 more, see `Safe methods`_ in the HTTP spec. 1391 1392 .. _Safe methods: http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html#sec9.1.1 1393 1345 1394 bulk_create 1346 1395 ~~~~~~~~~~~ 1347 1396 -
new file tests/modeltests/update_or_create/models.py
diff --git a/tests/modeltests/update_or_create/__init__.py b/tests/modeltests/update_or_create/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/modeltests/update_or_create/models.py b/tests/modeltests/update_or_create/models.py new file mode 100644 index 0000000..32ac33f
- + 1 """ 2 XX. update_or_create() 3 4 ``get_or_create()`` does what it says: it tries to look up an object with the 5 given parameters. If an object isn't found, it creates one with the given 6 parameters. Otherwise it updates the existing object with the given default 7 values. 8 """ 9 10 from django.db import models 11 12 class Person(models.Model): 13 first_name = models.CharField(max_length=100) 14 last_name = models.CharField(max_length=100) 15 birthday = models.DateField() 16 17 def __str__(self): 18 return '%s %s, Birthday: %s' % (self.first_name, self.last_name, 19 self.birthday) 20 21 class Meta: 22 ordering = ('last_name',) -
new file tests/modeltests/update_or_create/tests.py
diff --git a/tests/modeltests/update_or_create/tests.py b/tests/modeltests/update_or_create/tests.py new file mode 100644 index 0000000..53c3d33
- + 1 from __future__ import absolute_import 2 3 from datetime import date 4 5 from django.test import TestCase 6 7 from .models import Person 8 9 10 class UpdateOrCreateTests(TestCase): 11 def test_update_or_create(self): 12 Person.objects.create( 13 first_name='John', last_name='Lennon', birthday=date(1940, 10, 9) 14 ) 15 16 p, created = Person.objects.update_or_create( 17 first_name='John', last_name='Lennon', defaults={ 18 'birthday': date(1970, 10, 9) 19 } 20 ) 21 self.assertFalse(created) 22 self.assertEqual(Person.objects.count(), 1) 23 24 p, created = Person.objects.update_or_create( 25 first_name='George', last_name='Harrison', defaults={ 26 'birthday': date(1943, 2, 25) 27 } 28 ) 29 self.assertTrue(created) 30 self.assertEqual(Person.objects.count(), 2) 31 32 # If we execute the exact same statement, it won't create a Person. 33 p, created = Person.objects.update_or_create( 34 first_name='George', last_name='Harrison', defaults={ 35 'birthday': date(1943, 2, 25) 36 } 37 ) 38 self.assertFalse(created) 39 self.assertEqual(Person.objects.count(), 2) 40 41 # update_or_create() can take an empty 'defaults' parameter, but in 42 # this situation behaves exactly like get_or_create(). This is useful 43 # if you are building the 'defaults' dictionary dynamically. 44 p, created = Person.objects.update_or_create( 45 first_name='George', last_name='Harrison', defaults={} 46 ) 47 self.assertFalse(created) 48 49 # A different name with an empty 'defaults'. 50 p, created = Person.objects.update_or_create( 51 first_name='John', last_name='Smith', birthday=date(1950, 2, 10), 52 defaults={} 53 ) 54 self.assertTrue(created) 55 self.assertEqual(Person.objects.count(), 3)