Django provides a get_or_create
helper method in the models.Manager
class which looks up an object for the given kwargs
, creating one if necessary. But sometime you need a method which updates the object with given kwargs
or creates it if it's not found. This snippet provides the helper for that purpose.
Use the snippet like this:
from django.db import models
class PersonManager(models.Manager):
update_or_create = _update_or_create
class Person(models.Model):
first_name = models.CharField()
last_name = models.CharField()
city = models.CharField()
objects = PersonManager()
person, created, updated = Person.objects.update_or_create(first_name="John",
last_name="Smith", defaults=dict(city="London"))
The method returns a tuple of (object
, created
, updated
), where created
and updated
are booleans specifying whether an object
was created or updated respectively. Both created
and updated
are false
if object
is neither created nor updated (that is object
has just been fetched "as is" from db). This happens if the update fails.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | from django.db import transaction, IntegrityError
def _update_or_create(self, **kwargs):
assert kwargs, \
'update_or_create() must be passed at least one keyword argument'
obj, created = self.get_or_create(**kwargs)
defaults = kwargs.pop('defaults', {})
if created:
return obj, True, False
else:
try:
params = dict([(k, v) for k, v in kwargs.items() if '__' not in k])
params.update(defaults)
for attr, val in params.items():
if hasattr(obj, attr):
setattr(obj, attr, val)
sid = transaction.savepoint()
obj.save(force_update=True)
transaction.savepoint_commit(sid)
return obj, False, True
except IntegrityError, e:
transaction.savepoint_rollback(sid)
try:
return self.get(**kwargs), False, False
except self.model.DoesNotExist:
raise e
|
More like this
- Browser-native date input field by kytta 1 month, 1 week ago
- Generate and render HTML Table by LLyaudet 1 month, 2 weeks ago
- My firs Snippets by GutemaG 1 month, 3 weeks ago
- FileField having auto upload_to path by junaidmgithub 2 months, 4 weeks ago
- LazyPrimaryKeyRelatedField by LLyaudet 3 months, 1 week ago
Comments
Please login first before commenting.