MCPcopy
hub / github.com/django/django / bulk_update

Method bulk_update

django/db/models/query.py:952–1008  ·  view source on GitHub ↗

Update the given fields in each of the given objects in the database.

(self, objs, fields, batch_size=None)

Source from the content-addressed store, hash-verified

950 abulk_create.alters_data = True
951
952 def bulk_update(self, objs, fields, batch_size=None):
953 """
954 Update the given fields in each of the given objects in the database.
955 """
956 if batch_size is not None and batch_size <= 0:
957 raise ValueError("Batch size must be a positive integer.")
958 if not fields:
959 raise ValueError("Field names must be given to bulk_update().")
960 objs = tuple(objs)
961 if not all(obj._is_pk_set() for obj in objs):
962 raise ValueError("All bulk_update() objects must have a primary key set.")
963 opts = self.model._meta
964 fields = [opts.get_field(name) for name in fields]
965 if any(not f.concrete for f in fields):
966 raise ValueError("bulk_update() can only be used with concrete fields.")
967 all_pk_fields = set(opts.pk_fields)
968 for parent in opts.all_parents:
969 all_pk_fields.update(parent._meta.pk_fields)
970 if any(f in all_pk_fields for f in fields):
971 raise ValueError("bulk_update() cannot be used with primary key fields.")
972 if not objs:
973 return 0
974 for obj in objs:
975 obj._prepare_related_fields_for_save(
976 operation_name="bulk_update", fields=fields
977 )
978 # PK is used twice in the resulting update query, once in the filter
979 # and once in the WHEN. Each field will also have one CAST.
980 self._for_write = True
981 connection = connections[self.db]
982 max_batch_size = connection.ops.bulk_batch_size(
983 [opts.pk, opts.pk, *fields], objs
984 )
985 batch_size = min(batch_size, max_batch_size) if batch_size else max_batch_size
986 requires_casting = connection.features.requires_casted_case_in_updates
987 batches = (objs[i : i + batch_size] for i in range(0, len(objs), batch_size))
988 updates = []
989 for batch_objs in batches:
990 update_kwargs = {}
991 for field in fields:
992 when_statements = []
993 for obj in batch_objs:
994 attr = getattr(obj, field.attname)
995 if not hasattr(attr, "resolve_expression"):
996 attr = Value(attr, output_field=field)
997 when_statements.append(When(pk=obj.pk, then=attr))
998 case_statement = Case(*when_statements, output_field=field)
999 if requires_casting:
1000 case_statement = Cast(case_statement, output_field=field)
1001 update_kwargs[field.attname] = case_statement
1002 updates.append(([obj.pk for obj in batch_objs], update_kwargs))
1003 rows_updated = 0
1004 queryset = self.using(self.db)
1005 with transaction.atomic(using=self.db, savepoint=False):
1006 for pks, update_kwargs in updates:
1007 rows_updated += queryset.filter(pk__in=pks).update(**update_kwargs)
1008 return rows_updated
1009

Callers 15

handleMethod · 0.45
method_set_orderFunction · 0.45
test_simpleMethod · 0.45
test_multiple_fieldsMethod · 0.45
test_batch_sizeMethod · 0.45
test_max_batch_sizeMethod · 0.45
test_unsaved_modelsMethod · 0.45
test_functionsMethod · 0.45
test_no_fieldsMethod · 0.45

Calls 12

usingMethod · 0.95
ValueClass · 0.90
WhenClass · 0.90
CaseClass · 0.90
CastClass · 0.90
_is_pk_setMethod · 0.80
bulk_batch_sizeMethod · 0.80
get_fieldMethod · 0.45
updateMethod · 0.45
appendMethod · 0.45
filterMethod · 0.45

Tested by 15

test_simpleMethod · 0.36
test_multiple_fieldsMethod · 0.36
test_batch_sizeMethod · 0.36
test_max_batch_sizeMethod · 0.36
test_unsaved_modelsMethod · 0.36
test_functionsMethod · 0.36
test_no_fieldsMethod · 0.36