[python] 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?

This question is related to python django models

The answer is


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()

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 am using the following code in such cases:

obj, created = Model.objects.get_or_create(id=some_id)

if not created:
   resp= "It was created"
else:
   resp= "OK"
   obj.save()

As @Nils mentionned, you can use the update_fields keyword argument of the save() method to manually specify the fields to update.

obj_instance = Model.objects.get(field=value)
obj_instance.field = new_value
obj_instance.field2 = new_value2

obj_instance.save(update_fields=['field', 'field2'])

The update_fields value should be a list of the fields to update as strings.

See https://docs.djangoproject.com/en/2.1/ref/models/instances/#specifying-which-fields-to-save


Here's a mixin that you can mix into any model class which gives each instance an update method:

class UpdateMixin(object):
    def update(self, **kwargs):
        if self._state.adding:
            raise self.DoesNotExist
        for field, value in kwargs.items():
            setattr(self, field, value)
        self.save(update_fields=kwargs.keys())

The self._state.adding check checks to see if the model is saved to the database, and if not, raises an error.

(Note: This update method is for when you want to update a model and you know the instance is already saved to the database, directly answering the original question. The built-in update_or_create method featured in Platinum Azure's answer already covers the other use-case.)

You would use it like this (after mixing this into your user model):

user = request.user
user.update(favorite_food="ramen")

Besides having a nicer API, another advantage to this approach is that it calls the pre_save and post_save hooks, while still avoiding atomicity issues if another process is updating the same model.


Examples related to python

programming a servo thru a barometer Is there a way to view two blocks of code from the same file simultaneously in Sublime Text? python variable NameError Why my regexp for hyphenated words doesn't work? Comparing a variable with a string python not working when redirecting from bash script is it possible to add colors to python output? Get Public URL for File - Google Cloud Storage - App Engine (Python) Real time face detection OpenCV, Python xlrd.biffh.XLRDError: Excel xlsx file; not supported Could not load dynamic library 'cudart64_101.dll' on tensorflow CPU-only installation

Examples related to django

How to fix error "ERROR: Command errored out with exit status 1: python." when trying to install django-heroku using pip Pylint "unresolved import" error in Visual Studio Code Is it better to use path() or url() in urls.py for django 2.0? Unable to import path from django.urls Error loading MySQLdb Module 'Did you install mysqlclient or MySQL-python?' ImportError: Couldn't import Django Django - Reverse for '' not found. '' is not a valid view function or pattern name Class has no objects member Getting TypeError: __init__() missing 1 required positional argument: 'on_delete' when trying to add parent table after child table with entries How to switch Python versions in Terminal?

Examples related to models

Class 'App\Http\Controllers\DB' not found and I also cannot use a new Model How can I get the username of the logged-in user in Django? Django: Calling .update() on a single model instance retrieved by .get()?