#27335: Avoid object save during QuerySet.update_or_create when there were no
changes
----------------------------------------------+--------------------
Reporter: tonnzor | Owner: nobody
Type: Cleanup/optimization | Status: new
Component: Database layer (models, ORM) | Version: master
Severity: Normal | Keywords:
Triage Stage: Unreviewed | Has patch: 0
Easy pickings: 0 | UI/UX: 0
----------------------------------------------+--------------------
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.
--
Ticket URL: <https://code.djangoproject.com/ticket/27335>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/050.4e2e256a5cdeb082cf9ea4ebfa1f9af2%40djangoproject.com.
For more options, visit https://groups.google.com/d/optout.