Search code examples
pythondjangomodeldjango-orm

How to update() a single model instance retrieved by get() on Django ORM?


I have a function which currently calls Models.object.get(), which returns either 0 or 1 model objects:

  • if it returns 0, I create a new model instance in the except DoesNotExist clause of the function.
  • Otherwise, I would like to update the fields in the pre-existing instance, without creating a new one.

I was originally attempting to call .update() on the instance which was found, but .update() seems to be only callable on a QuerySets. How do I get around changing a dozen fields, without calling .filter() and comparing the lengths to know if I have to create or update a pre-existing instance?


Solution

  • With the advent of Django 1.7, there is now a new update_or_create QuerySet method, which should do exactly what you want. Just be careful of potential race conditions if uniqueness is not enforced at the database level.

    Example from the documentation:

    obj, created = Person.objects.update_or_create(
        first_name='John', last_name='Lennon',
        defaults={'first_name': 'Bob'},
    )
    

    The update_or_create method tries to fetch an object from database based on the given kwargs. If a match is found, it updates the fields passed in the defaults dictionary.


    Pre-Django 1.7:

    Change the model field values as appropriate, then call .save() to persist the changes:

    try:
        obj = Model.objects.get(field=value)
        obj.field = new_value
        obj.save()
    except Model.DoesNotExist:
        obj = Model.objects.create(field=new_value)
    # do something else with obj if need be