Django: Calling .update() on a single model instance retrieved by .get()?
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?
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 thedefaults
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
if you want only to update model if exist (without create it):
Model.objects.filter(id = 223).update(field1 = 2)
mysql query:
UPDATE `model` SET `field1` = 2 WHERE `model`.`id` = 223
As of Django 1.5, there is an update_fields property on model save. eg:
obj.save(update_fields=['field1', 'field2', ...])
https://docs.djangoproject.com/en/dev/ref/models/instances/
I prefer this approach because it doesn't create an atomicity problem if you have multiple web app instances changing different parts of a model instance.
I don't know how good or bad this is, but you can try something like this:
try:
obj = Model.objects.get(id=some_id)
except Model.DoesNotExist:
obj = Model.objects.create()
obj.__dict__.update(your_fields_dict)
obj.save()