How do I use a dictionary to update fields in Django models?
Solution 1
Here's an example of create using your dictionary d:
Book.objects.create(**d)
To update an existing model, you will need to use the QuerySet filter
method. Assuming you know the pk
of the Book you want to update:
Book.objects.filter(pk=pk).update(**d)
Solution 2
Use **
for creating a new model. Loop through the dictionary and use setattr()
in order to update an existing model.
From Tom Christie's Django Rest Framework
https://github.com/tomchristie/django-rest-framework/blob/master/rest_framework/serializers.py
for attr, value in validated_data.items():
setattr(instance, attr, value)
instance.save()
Solution 3
If you know you would like to create it:
Book.objects.create(**d)
Assuming you need to check for an existing instance, you can find it with get or create:
instance, created = Book.objects.get_or_create(slug=slug, defaults=d)
if not created:
for attr, value in d.items():
setattr(instance, attr, value)
instance.save()
As mentioned in another answer, you can also use the update
function on the queryset manager, but i believe that will not send any signals out (which may not matter to you if you aren't using them). However, you probably shouldn't use it to alter a single object:
Book.objects.filter(id=id).update()
Solution 4
if you have already Django object and you want to update it's field, you may do it without filter. because you have it already, in this case, yoy may :
your_obj.__dict__.update(your_dict)
your_obj.save()
Solution 5
To update one record you can use very handy function:
class Book(models.Model):
num_pages = ...
author = ...
date = ...
def update(self,*args, **kwargs):
for name,values in kwargs.items():
try:
setattr(self,name,values)
except KeyError:
pass
self.save()
and then:
d = {"num_pages":40, author:"Jack", date:"3324"}
book = Book.objects.first()
book.update(**d)
Related videos on Youtube
TIMEX
Updated on August 21, 2021Comments
-
TIMEX over 2 years
Suppose I have a model like this:
class Book(models.Model): num_pages = ... author = ... date = ...
Can I create a dictionary, and then insert or update the model using it?
d = {"num_pages":40, author:"Jack", date:"3324"}
-
user1066101 about 13 yearsYes. Try it. Look up the
**
operator in the Python language reference manual. docs.python.org/reference/expressions.html#calls -
user1066101 about 13 yearspossible duplicate of Update model django through kwargs
-
-
TIMEX about 13 yearsHuh? Can you give an example? So, I would have to write a custom function that loops through the dictionary?
-
user1066101 about 13 years@TIMEX: Please read. docs.python.org/reference/expressions.html#calls is very clear on how this works.
-
Thierry Lam over 10 yearsI think update only works on a QuerySet not on a single object.
-
Jorge Leitao about 10 yearsDoesn't your create code leads to 2 database hits? One for creating, the other for
.save()
? -
leech about 10 yearsYes, but not to save. If it has been created, there will be one to lookup the Book (SELECT), then another to update it (an UPDATE not INSERT statement will be generated). If the book doesn't exist, there is one to look it up (SELECT) and create it (INSERT).
-
redacted over 7 yearsCould you explain why using
**
for updating might not be a good idea? -
CrowbarKZ over 7 years@Pocin using
queryset.update(**fields)
is a good idea according to django docs. Quote: "If you’re just updating a record and don’t need to do anything with the model object, the most efficient approach is to call update(), rather than loading the model object into memory." -
Wtower about 7 yearsBe careful:
update()
does not respect signals. See the answer by @leech below. -
Wtower about 7 years
that will not send any signals out
: cannot stress this out enough. -
Bryant James almost 7 yearsGood answer, the call is very explicit. Not a fan of filter(...).update(...) since bungling the filter can lead to mass overwrites.
-
MikeyE almost 4 yearsI agree with Bryant Jackson. And also it seems a bit easier to understand the code when operating on a single instance.
-
joshlsullivan over 3 yearsThis is brilliant.
-
Scott over 3 yearsPlease add a ".": your_obj.__dict__.update(your_dict)
-
radtek about 3 yearsHmm too bad update and update_or_create don't take using parameter, only save() does.
-
Gokberk Yar almost 3 yearsTLDR : Won't work for object fields. Details: If your fields are not basic types like str, int ie an object like Entry. It won't work.