54
Atomic transactions can reduce the time spent in the loop:
from django.db import transaction
with transaction.atomic():
for i, row in df.iterrows():
mv = MeasureValue.objects.get(org=row.org, month=month)
if (row.percentile is None) or np.isnan(row.percentile):
# if it's already None, why set it to None?
row.percentile = None
mv.percentile = row.percentile
mv.save()
Django’s default behavior is to run in autocommit mode. Each query is immediately committed to the database, unless a transaction is actives.
By using with transaction.atomic()
all the inserts are grouped into a single transaction. The time needed to commit the transaction is amortized over all the enclosed insert statements and so the time per insert statement is greatly reduced.
37
As of Django 2.2, you can use the bulk_update()
queryset method to efficiently update the given fields on the provided model instances, generally with one query:
objs = [
Entry.objects.create(headline='Entry 1'),
Entry.objects.create(headline='Entry 2'),
]
objs[0].headline = 'This is entry 1'
objs[1].headline = 'This is entry 2'
Entry.objects.bulk_update(objs, ['headline'])
In older versions of Django you could use update()
with Case
/When
, e.g.:
from django.db.models import Case, When
Entry.objects.filter(
pk__in=headlines # `headlines` is a pk -> headline mapping
).update(
headline=Case(*[When(pk=entry_pk, then=headline)
for entry_pk, headline in headlines.items()]))
- [Django]-Django: dependencies reference nonexistent parent node
- [Django]-Django query get last n records
- [Django]-How to set django model field by name?
1
In my case, we need Value
headlines is a pk -> headline mapping `{1, 'some_val1', 2, 'some_val2', ...}
from django.db.models import Case, When, Value
Entry.objects.filter(
pk__in=headlines
).update(
headline=Case(*[When(pk=entry_pk, then=Value(headline))
for entry_pk, headline in headlines.items()]))
- [Django]-Django model method – create_or_update
- [Django]-Django – {% csrf_token %} was used in a template, but the context did not provide the value
- [Django]-Django: Assigning variables in template
0
Actually, attempting @Eugene Yarmash ‘s answer I found I got this error:
FieldError: Joined field references are not permitted in this query
But I believe iterating update
is still quicker than multiple saves, and I expect using a transaction should also expedite.
So, for versions of Django that don’t offer bulk_update
, assuming the same data used in Eugene’s answer, where headlines
is a pk -> headline mapping:
from django.db import transaction
with transaction.atomic():
for entry_pk, headline in headlines.items():
Entry.objects.filter(pk=entry_pk).update(headline=headline)
- [Django]-"_set" in a queryset object in Django
- [Django]-Nginx doesn't serve static
- [Django]-Django excluding one queryset from another