2

I've an object:-

a = Model.objects.get(id=1)

and a dictionary of data attributes of object a.

update_data = {
colA: 1,
colB: 2,
colC: 3,
}

Now, I want to update object a. How can I do it?

Note:- .update() works on queryset, not on the object. Also, I cannot do a.colA=1 because in that case, I've use setattr on each key.

Is there any way that I can update the object directly?

Gahan
  • 4,075
  • 4
  • 24
  • 44
Praful Bagai
  • 16,684
  • 50
  • 136
  • 267

3 Answers3

4

You can use .update() method like this:

Model.objects.filter(id=1).update(**update_data)

or you can update the individual object (iterating in update_data dict), too:

a = Model.objects.get(id=1)

for name in update_data:
    setattr(a, name, update_data[name])

# don't forget to save the object after modifying
a.save()
Mundi
  • 79,884
  • 17
  • 117
  • 140
Gokhan Sari
  • 7,185
  • 5
  • 34
  • 32
  • Great answer! But I want to know if there is a quicker way to do this? As we know, the for loop in python is pretty slow. – Wang Honghui Sep 04 '22 at 05:08
3

I think you can do

a = Model.object.get(id=1)
a.__dict__.update(update_data)
itzMEonTV
  • 19,851
  • 4
  • 39
  • 49
2

For updating directly considering dictionary already constructed, you may filter objects first and then easily update the data, also filter() is faster then get() (*I have tested on small database size)

As you said in comment if you only have object (model instance) and dictionary you can write it as below:

Model.objects.filter(id=a.id).update(**update_data)

The performance result (tested on small db size) In [4]: g = Genres.objects.last()

In [6]: %timeit Genres.objects.get(id=g.id)
518 µs ± 10.9 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

In [7]: %timeit Genres.objects.filter(id=g.id)
74.2 µs ± 807 ns per loop (mean ± std. dev. of 7 runs, 10000 loops each)
Gahan
  • 4,075
  • 4
  • 24
  • 44