[Django]-Efficient way to update multiple fields of Django model object

68πŸ‘

βœ…

You can update a row in the database without fetching and deserializing it; update() can do it. E.g.:

User.objects.filter(id=data['id']).update(email=data['email'], phone=data['phone'])

This will issue one SQL update statement, and is much faster than the code in your post. It will never fetch the data or waste time creating a User object.

You cannot, though, send a whole bunch of update data to the SQL database and ask it to map it to different rows in one go. If you need a massive update like that done very quickly, your best bet is probably inserting the data into a separate table and then update it form a select on that table. Django ORM does not support this, as far as I can tell.

32πŸ‘

Even simpler if you use .update() method of QuerySet object as:

my_id = fetched_data.pop('id')  # remove 'id' from `fetch_data`
                                # as it is not supposed to be updated

User.objects.filter(pk=my_id).update(**fetched_data)
#          unpack the content of `dict` ^

It will unpack the content of fetched_data dict and will update the records in User object whose columns are present as key to the fetched_data dict. Since you are calling filter on pk, it will always return single record.

16πŸ‘

If you use .update then there is an issue, since it won’t raise post_save or pre_save signal, so if you want to use any signal on any change of data then User.objects.filter(pk=fetched_data['id']).update(**kwargs) won’t work.

So you can use setattr() to update the fields and then .save would save the row which would update the row also raise an signal.

old_user = User.objects.get(pk=fetched_data['id'])
for key, value in fetched_data.iteritems():
    setattr(old_user, key, value)
old_user.save()

6πŸ‘

setattr(old_user, fetched_data_key, fetched_data['fetched_data_key'])

1πŸ‘

User.objects.filter(pk=fetched_data['id']).update(**kwargs)

this will update multiple fields. But it won’t call signals, So if there is any signal written for this model then it will not run.

So better to use setattr() method to set new data into the fields, then call .save() method and it will run the signal also.

user = User.objects.get(pk=fetched_data['id'])
for key, value in fetched_data.items():
    setattr(user, key, value)
user.save()

-1πŸ‘

Blackquotes

def update_block(request, id):

a = RentedNumberBlock.objects.get(id=id)
b = RentedNumber.objects.filter(user=request.user)
c = a.rented_number.values_list('id', flat=True)
if request.POST:
    update = RentedNumberBlock.objects.get(id=id)
    update.name = request.POST['name']
    z = dict(request.POST)['rented_number']
    y = RentedNumber.objects.filter(id__in=z)
    update.rented_number.set(z)
    update.save()
    return HttpResponseRedirect('/block/')
return render(request, "block/update.html", {"a": a , "b": b, "c": c})

Leave a comment