﻿id	summary	reporter	owner	description	type	status	component	version	severity	resolution	keywords	cc	stage	has_patch	needs_docs	needs_tests	needs_better_patch	easy	ui_ux
27335	Avoid object save during QuerySet.update_or_create() when there were no changes	Artem Skoretskiy	Andrew Nester	"Right now when you use QuerySet.update_or_create -- it always saves into DB even if there were no changes.

It would be great that if nothing is changed -- nothing is saved into DB. I found myself often reusing the same pattern in our projects.

Use case:

{{{#!python
>>> from django.contrib.auth.models import User
>>> User.objects.create(is_superuser=True, username='admin', is_active=True) # generate a use in DB to work with
>>> # later in our code
>>> user, created = User.objects.update_or_create(defaults={'is_active': True}, username='admin')
# here an extra DB write though no data were changed
}}}

If you check the current code in master (https://github.com/django/django/blob/master/django/db/models/query.py#L477):
{{{#!python
            try:
                obj = self.select_for_update().get(**lookup)
            except self.model.DoesNotExist:
                obj, created = self._create_object_from_params(lookup, params)
                if created:
                    return obj, created
            for k, v in six.iteritems(defaults):
                setattr(obj, k, v() if callable(v) else v)
            obj.save(using=self.db) # HERE IT IS => always save
}}}

If object exists in DB, it would apply all attributes from `default` and save it even if there were no changes in values.

We could do something like that:
{{{#!python
            changed = False
            for k, v in six.iteritems(defaults):
                v = v() if callable(v) else v
                if v != getattr(obj, k):
                    modified = True
                    setattr(obj, k, v)
            if changed:
                obj.save(using=self.db) # save only if there were changes
}}}

If you think it is too complex for all use cases, we may put a flag for enabling / disabling this feature or have another method for this logic."	Cleanup/optimization	closed	Database layer (models, ORM)	dev	Normal	wontfix			Accepted	0	0	0	0	0	0
