How to select a record and update it, with a single queryset in Django?

SqlDjangoDjango ModelsOrmDjango Queryset

Sql Problem Overview


How do I run an update and select statements on the same queryset rather than having to do two queries:

  • one to select the object
  • and one to update the object

The equivalent in SQL would be something like:

update my_table set field_1 = 'some value' where pk_field = some_value

Sql Solutions


Solution 1 - Sql

Use the queryset object update method:

MyModel.objects.filter(pk=some_value).update(field1='some value')

Solution 2 - Sql

Django database objects use the same save() method for creating and changing objects.

obj = Product.objects.get(pk=pk)
obj.name = "some_new_value"
obj.save()

> How Django knows to UPDATE vs. INSERT
> If the object’s primary key attribute is set to a value that evaluates to True (i.e., a value > other than None or the empty string), Django executes an UPDATE. If > the object’s primary key attribute is not set or if the UPDATE didn’t > update anything, Django executes an INSERT.

Ref.: https://docs.djangoproject.com/en/1.9/ref/models/instances/

Solution 3 - Sql

This answer compares the above two approaches. If you want to update many objects in a single line, go for:

# Approach 1
MyModel.objects.filter(field1='Computer').update(field2='cool')

Otherwise you would have to iterate over the query set and update individual objects:

#Approach 2    
objects = MyModel.objects.filter(field1='Computer')
for obj in objects:
    obj.field2 = 'cool'
    obj.save()
  1. Approach 1 is faster because, it makes only one database query, compared to approach 2 which makes 'n+1' database queries. (For n items in the query set)

  2. Fist approach makes one db query ie UPDATE, the second one makes two: SELECT and then UPDATE.

  3. The tradeoff is that, suppose you have any triggers, like updating updated_on or any such related fields, it will not be triggered on direct update ie approach 1.

  4. Approach 1 is used on a queryset, so it is possible to update multiple objects at once, not in the case of approach 2.

Solution 4 - Sql

1st method

MyTable.objects.filter(pk=some_value).update(field1='some value')

2nd Method

q = MyModel.objects.get(pk=some_value)
q.field1 = 'some value'
q.save()

3rd method

By using get_object_or_404

q = get_object_or_404(MyModel,pk=some_value)
q.field1 = 'some value'
q.save()

4th Method

if you required if pk=some_value exist then update it other wise create new one by using update_or_create.

MyModel.objects.update_or_create(pk=some_value,defaults={'field1':'some value'})

Solution 5 - Sql

If you need to set the new value based on the old field value that is do something like:

update my_table set field_1 = field_1 + 1 where pk_field = some_value

use query expressions:

MyModel.objects.filter(pk=some_value).update(field1=F('field1') + 1)

This will execute update atomically that is using one update request to the database without reading it first.

Solution 6 - Sql

only in a case in serializer things, you can update in very simple way!

my_model_serializer = MyModelSerializer(
    instance=my_model, data=validated_data)
if my_model_serializer.is_valid():

    my_model_serializer.save()

only in a case in form things!

instance = get_object_or_404(MyModel, id=id)
form = MyForm(request.POST or None, instance=instance)
if form.is_valid():
    form.save()

Solution 7 - Sql

Accepted answer works great, but it comes with some unwanted side effect.

For example, you are using imageField, the update() will work and update others data, but not update your imageField data

class ProfileSetting(models.Model):

    first_name = models.CharField(blank=True)

    logo = models.ImageField(blank=True, null=True, upload_to="profile/logo/")

update_data = {
  "first_name": "john",
  "logo": request.FILES['logo'] # logo will not be properly update
}

ProfileSetting.objects.filter(pk=some_value).update(**update_data)

Here is some example with good explanation https://stackoverflow.com/questions/54040591/django-imagefield-is-not-updating-when-update-method-is-used

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJohnView Question on Stackoverflow
Solution 1 - SqlDaniel RosemanView Answer on Stackoverflow
Solution 2 - SqlSlipstreamView Answer on Stackoverflow
Solution 3 - SqlPransh TiwariView Answer on Stackoverflow
Solution 4 - SqlRiyas AcView Answer on Stackoverflow
Solution 5 - SqlRoman-Stop RU aggression in UAView Answer on Stackoverflow
Solution 6 - SqlJamil NoydaView Answer on Stackoverflow
Solution 7 - SqlcyberflyView Answer on Stackoverflow