Login

update_or_create

Author:
abhin4v
Posted:
October 7, 2008
Language:
Python
Version:
1.0
Tags:
model helper update create
Score:
2 (after 6 ratings)

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

  1. DRY Fieldsets by DrMeers 5 years, 9 months ago
  2. Modifying the fields of a third/existing model class by marinho 4 years, 3 months ago
  3. CustomQueryManager by zvoase 6 years, 8 months ago
  4. Allow filtering and ordering by counts of related query results by exogen 7 years, 11 months ago
  5. object-oriented generic views by carljm 6 years, 7 months ago

Comments

Please login first before commenting.