Loading django/db/models/base.py +1 −1 Original line number Diff line number Diff line Loading @@ -833,7 +833,7 @@ class Model(six.with_metaclass(ModelBase)): collector = Collector(using=using) collector.collect([self], keep_parents=keep_parents) collector.delete() return collector.delete() delete.alters_data = True Loading django/db/models/deletion.py +8 −3 Original line number Diff line number Diff line from collections import OrderedDict from collections import Counter, OrderedDict from itertools import chain from operator import attrgetter Loading Loading @@ -280,6 +280,8 @@ class Collector(object): # don't support transactions or cannot defer constraint checks until the # end of a transaction. self.sort() # number of objects deleted for each model label deleted_counter = Counter() with transaction.atomic(using=self.using, savepoint=False): # send pre_delete signals Loading @@ -291,7 +293,8 @@ class Collector(object): # fast deletes for qs in self.fast_deletes: qs._raw_delete(using=self.using) count = qs._raw_delete(using=self.using) deleted_counter[qs.model._meta.label] += count # update fields for model, instances_for_fieldvalues in six.iteritems(self.field_updates): Loading @@ -308,7 +311,8 @@ class Collector(object): for model, instances in six.iteritems(self.data): query = sql.DeleteQuery(model) pk_list = [obj.pk for obj in instances] query.delete_batch(pk_list, self.using) count = query.delete_batch(pk_list, self.using) deleted_counter[model._meta.label] += count if not model._meta.auto_created: for obj in instances: Loading @@ -324,3 +328,4 @@ class Collector(object): for model, instances in six.iteritems(self.data): for instance in instances: setattr(instance, model._meta.pk.attname, None) return sum(deleted_counter.values()), dict(deleted_counter) django/db/models/query.py +4 −2 Original line number Diff line number Diff line Loading @@ -590,10 +590,12 @@ class QuerySet(object): collector = Collector(using=del_query.db) collector.collect(del_query) collector.delete() deleted, _rows_count = collector.delete() # Clear the result cache, in case this QuerySet gets reused. self._result_cache = None return deleted, _rows_count delete.alters_data = True delete.queryset_only = True Loading @@ -602,7 +604,7 @@ class QuerySet(object): Deletes objects found from the given queryset in single direct SQL query. No signals are sent, and there is no protection for cascades. """ sql.DeleteQuery(self.model).delete_qs(self, using) return sql.DeleteQuery(self.model).delete_qs(self, using) _raw_delete.alters_data = True def update(self, **kwargs): Loading django/db/models/sql/subqueries.py +12 −6 Original line number Diff line number Diff line Loading @@ -5,7 +5,9 @@ Query subclasses which provide extra functionality beyond simple data retrieval. from django.core.exceptions import FieldError from django.db import connections from django.db.models.query_utils import Q from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE, NO_RESULTS from django.db.models.sql.constants import ( CURSOR, GET_ITERATOR_CHUNK_SIZE, NO_RESULTS, ) from django.db.models.sql.query import Query from django.utils import six Loading @@ -23,7 +25,8 @@ class DeleteQuery(Query): def do_query(self, table, where, using): self.tables = [table] self.where = where self.get_compiler(using).execute_sql(NO_RESULTS) cursor = self.get_compiler(using).execute_sql(CURSOR) return cursor.rowcount if cursor else 0 def delete_batch(self, pk_list, using, field=None): """ Loading @@ -32,13 +35,16 @@ class DeleteQuery(Query): More than one physical query may be executed if there are a lot of values in pk_list. """ # number of objects deleted num_deleted = 0 if not field: field = self.get_meta().pk for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): self.where = self.where_class() self.add_q(Q( **{field.attname + '__in': pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]})) self.do_query(self.get_meta().db_table, self.where, using=using) num_deleted += self.do_query(self.get_meta().db_table, self.where, using=using) return num_deleted def delete_qs(self, query, using): """ Loading @@ -63,8 +69,7 @@ class DeleteQuery(Query): values = list(query.values_list('pk', flat=True)) if not values: return self.delete_batch(values, using) return return self.delete_batch(values, using) else: innerq.clear_select_clause() innerq.select = [ Loading @@ -73,7 +78,8 @@ class DeleteQuery(Query): values = innerq self.where = self.where_class() self.add_q(Q(pk__in=values)) self.get_compiler(using).execute_sql(NO_RESULTS) cursor = self.get_compiler(using).execute_sql(CURSOR) return cursor.rowcount if cursor else 0 class UpdateQuery(Query): Loading docs/ref/models/instances.txt +6 −1 Original line number Diff line number Diff line Loading @@ -537,7 +537,8 @@ Deleting objects Issues an SQL ``DELETE`` for the object. This only deletes the object in the database; the Python instance will still exist and will still have data in its fields. its fields. This method returns the number of objects deleted and a dictionary with the number of deletions per object type. For more details, including how to delete objects in bulk, see :ref:`topics-db-queries-delete`. Loading @@ -553,6 +554,10 @@ keep the parent model's data. The ``keep_parents`` parameter was added. .. versionchanged:: 1.9 The return value describing the number of objects deleted was added. Pickling objects ================ Loading Loading
django/db/models/base.py +1 −1 Original line number Diff line number Diff line Loading @@ -833,7 +833,7 @@ class Model(six.with_metaclass(ModelBase)): collector = Collector(using=using) collector.collect([self], keep_parents=keep_parents) collector.delete() return collector.delete() delete.alters_data = True Loading
django/db/models/deletion.py +8 −3 Original line number Diff line number Diff line from collections import OrderedDict from collections import Counter, OrderedDict from itertools import chain from operator import attrgetter Loading Loading @@ -280,6 +280,8 @@ class Collector(object): # don't support transactions or cannot defer constraint checks until the # end of a transaction. self.sort() # number of objects deleted for each model label deleted_counter = Counter() with transaction.atomic(using=self.using, savepoint=False): # send pre_delete signals Loading @@ -291,7 +293,8 @@ class Collector(object): # fast deletes for qs in self.fast_deletes: qs._raw_delete(using=self.using) count = qs._raw_delete(using=self.using) deleted_counter[qs.model._meta.label] += count # update fields for model, instances_for_fieldvalues in six.iteritems(self.field_updates): Loading @@ -308,7 +311,8 @@ class Collector(object): for model, instances in six.iteritems(self.data): query = sql.DeleteQuery(model) pk_list = [obj.pk for obj in instances] query.delete_batch(pk_list, self.using) count = query.delete_batch(pk_list, self.using) deleted_counter[model._meta.label] += count if not model._meta.auto_created: for obj in instances: Loading @@ -324,3 +328,4 @@ class Collector(object): for model, instances in six.iteritems(self.data): for instance in instances: setattr(instance, model._meta.pk.attname, None) return sum(deleted_counter.values()), dict(deleted_counter)
django/db/models/query.py +4 −2 Original line number Diff line number Diff line Loading @@ -590,10 +590,12 @@ class QuerySet(object): collector = Collector(using=del_query.db) collector.collect(del_query) collector.delete() deleted, _rows_count = collector.delete() # Clear the result cache, in case this QuerySet gets reused. self._result_cache = None return deleted, _rows_count delete.alters_data = True delete.queryset_only = True Loading @@ -602,7 +604,7 @@ class QuerySet(object): Deletes objects found from the given queryset in single direct SQL query. No signals are sent, and there is no protection for cascades. """ sql.DeleteQuery(self.model).delete_qs(self, using) return sql.DeleteQuery(self.model).delete_qs(self, using) _raw_delete.alters_data = True def update(self, **kwargs): Loading
django/db/models/sql/subqueries.py +12 −6 Original line number Diff line number Diff line Loading @@ -5,7 +5,9 @@ Query subclasses which provide extra functionality beyond simple data retrieval. from django.core.exceptions import FieldError from django.db import connections from django.db.models.query_utils import Q from django.db.models.sql.constants import GET_ITERATOR_CHUNK_SIZE, NO_RESULTS from django.db.models.sql.constants import ( CURSOR, GET_ITERATOR_CHUNK_SIZE, NO_RESULTS, ) from django.db.models.sql.query import Query from django.utils import six Loading @@ -23,7 +25,8 @@ class DeleteQuery(Query): def do_query(self, table, where, using): self.tables = [table] self.where = where self.get_compiler(using).execute_sql(NO_RESULTS) cursor = self.get_compiler(using).execute_sql(CURSOR) return cursor.rowcount if cursor else 0 def delete_batch(self, pk_list, using, field=None): """ Loading @@ -32,13 +35,16 @@ class DeleteQuery(Query): More than one physical query may be executed if there are a lot of values in pk_list. """ # number of objects deleted num_deleted = 0 if not field: field = self.get_meta().pk for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): self.where = self.where_class() self.add_q(Q( **{field.attname + '__in': pk_list[offset:offset + GET_ITERATOR_CHUNK_SIZE]})) self.do_query(self.get_meta().db_table, self.where, using=using) num_deleted += self.do_query(self.get_meta().db_table, self.where, using=using) return num_deleted def delete_qs(self, query, using): """ Loading @@ -63,8 +69,7 @@ class DeleteQuery(Query): values = list(query.values_list('pk', flat=True)) if not values: return self.delete_batch(values, using) return return self.delete_batch(values, using) else: innerq.clear_select_clause() innerq.select = [ Loading @@ -73,7 +78,8 @@ class DeleteQuery(Query): values = innerq self.where = self.where_class() self.add_q(Q(pk__in=values)) self.get_compiler(using).execute_sql(NO_RESULTS) cursor = self.get_compiler(using).execute_sql(CURSOR) return cursor.rowcount if cursor else 0 class UpdateQuery(Query): Loading
docs/ref/models/instances.txt +6 −1 Original line number Diff line number Diff line Loading @@ -537,7 +537,8 @@ Deleting objects Issues an SQL ``DELETE`` for the object. This only deletes the object in the database; the Python instance will still exist and will still have data in its fields. its fields. This method returns the number of objects deleted and a dictionary with the number of deletions per object type. For more details, including how to delete objects in bulk, see :ref:`topics-db-queries-delete`. Loading @@ -553,6 +554,10 @@ keep the parent model's data. The ``keep_parents`` parameter was added. .. versionchanged:: 1.9 The return value describing the number of objects deleted was added. Pickling objects ================ Loading