mirror of
				https://github.com/django/django.git
				synced 2025-10-30 09:06:13 +00:00 
			
		
		
		
	magic-removal: Fixed #1219 - Added bulk delete for objects.
git-svn-id: http://code.djangoproject.com/svn/django/branches/magic-removal@2029 bcc190cf-cafb-0310-a4f2-bffc1f526a37
This commit is contained in:
		| @@ -48,7 +48,7 @@ class Manager(object): | ||||
|            self.creation_counter < klass._default_manager.creation_counter: | ||||
|                 klass._default_manager = self | ||||
|  | ||||
|     def _get_sql_clause(self, *args, **kwargs): | ||||
|     def _get_sql_clause(self, allow_joins, *args, **kwargs): | ||||
|         def quote_only_if_word(word): | ||||
|             if ' ' in word: | ||||
|                 return word | ||||
| @@ -63,7 +63,7 @@ class Manager(object): | ||||
|         joins = SortedDict() | ||||
|         where = kwargs.get('where') and kwargs['where'][:] or [] | ||||
|         params = kwargs.get('params') and kwargs['params'][:] or [] | ||||
|  | ||||
|          | ||||
|         # Convert all the args into SQL. | ||||
|         table_count = 0 | ||||
|         for arg in args: | ||||
| @@ -77,7 +77,6 @@ class Manager(object): | ||||
|             where.extend(where2) | ||||
|             params.extend(params2) | ||||
|  | ||||
|  | ||||
|         # Convert the kwargs into SQL. | ||||
|         tables2, joins2, where2, params2 = parse_lookup(kwargs.items(), opts) | ||||
|         tables.extend(tables2) | ||||
| @@ -99,10 +98,14 @@ class Manager(object): | ||||
|         # Start composing the body of the SQL statement. | ||||
|         sql = [" FROM", backend.quote_name(opts.db_table)] | ||||
|  | ||||
|         # Check if extra tables are allowed. If not, throw an error | ||||
|         if (tables or joins) and not allow_joins: | ||||
|             raise TypeError("Joins are not allowed in this type of query") | ||||
|  | ||||
|         # Compose the join dictionary into SQL describing the joins. | ||||
|         if joins: | ||||
|             sql.append(" ".join(["%s %s AS %s ON %s" % (join_type, table, alias, condition) | ||||
|                                 for (alias, (table, join_type, condition)) in joins.items()])) | ||||
|                             for (alias, (table, join_type, condition)) in joins.items()])) | ||||
|  | ||||
|         # Compose the tables clause into SQL. | ||||
|         if tables: | ||||
| @@ -146,13 +149,28 @@ class Manager(object): | ||||
|  | ||||
|         return select, " ".join(sql), params | ||||
|  | ||||
|     def delete(self, *args, **kwargs): | ||||
|         # disable non-supported fields | ||||
|         kwargs['select_related'] = False | ||||
|         kwargs['select'] = {} | ||||
|         kwargs['order_by'] = [] | ||||
|         kwargs['offset'] = None | ||||
|         kwargs['limit'] = None | ||||
|          | ||||
|         opts = self.klass._meta | ||||
|  | ||||
|         # Perform the SQL delete | ||||
|         cursor = connection.cursor() | ||||
|         _, sql, params = self._get_sql_clause(False, *args, **kwargs) | ||||
|         cursor.execute("DELETE " + sql, params) | ||||
|          | ||||
|     def get_iterator(self, *args, **kwargs): | ||||
|         # kwargs['select'] is a dictionary, and dictionaries' key order is | ||||
|         # undefined, so we convert it to a list of tuples internally. | ||||
|         kwargs['select'] = kwargs.get('select', {}).items() | ||||
|  | ||||
|         cursor = connection.cursor() | ||||
|         select, sql, params = self._get_sql_clause(*args, **kwargs) | ||||
|         select, sql, params = self._get_sql_clause(True, *args, **kwargs) | ||||
|         cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params) | ||||
|         fill_cache = kwargs.get('select_related') | ||||
|         index_end = len(self.klass._meta.fields) | ||||
| @@ -177,7 +195,7 @@ class Manager(object): | ||||
|         kwargs['offset'] = None | ||||
|         kwargs['limit'] = None | ||||
|         kwargs['select_related'] = False | ||||
|         _, sql, params = self._get_sql_clause(*args, **kwargs) | ||||
|         _, sql, params = self._get_sql_clause(True, *args, **kwargs) | ||||
|         cursor = connection.cursor() | ||||
|         cursor.execute("SELECT COUNT(*)" + sql, params) | ||||
|         return cursor.fetchone()[0] | ||||
| @@ -209,7 +227,7 @@ class Manager(object): | ||||
|             fields = [f.column for f in self.klass._meta.fields] | ||||
|  | ||||
|         cursor = connection.cursor() | ||||
|         _, sql, params = self._get_sql_clause(*args, **kwargs) | ||||
|         _, sql, params = self._get_sql_clause(True, *args, **kwargs) | ||||
|         select = ['%s.%s' % (backend.quote_name(self.klass._meta.db_table), backend.quote_name(f)) for f in fields] | ||||
|         cursor.execute("SELECT " + (kwargs.get('distinct') and "DISTINCT " or "") + ",".join(select) + sql, params) | ||||
|         while 1: | ||||
| @@ -239,7 +257,7 @@ class Manager(object): | ||||
|         if field.null: | ||||
|             kwargs.setdefault('where', []).append('%s.%s IS NOT NULL' % \ | ||||
|                 (backend.quote_name(self.klass._meta.db_table), backend.quote_name(field.column))) | ||||
|         select, sql, params = self._get_sql_clause(*args, **kwargs) | ||||
|         select, sql, params = self._get_sql_clause(True, *args, **kwargs) | ||||
|         sql = 'SELECT %s %s GROUP BY 1 ORDER BY 1 %s' % \ | ||||
|             (backend.get_date_trunc_sql(kind, '%s.%s' % (backend.quote_name(self.klass._meta.db_table), | ||||
|             backend.quote_name(field.column))), sql, order) | ||||
|   | ||||
| @@ -203,6 +203,13 @@ Traceback (most recent call last): | ||||
|     ... | ||||
| AttributeError: Manager isn't accessible via Article instances | ||||
|  | ||||
| # Bulk delete test: How many objects before and after the delete? | ||||
| >>> Article.objects.get_count() | ||||
| 8L | ||||
| >>> Article.objects.delete(id__lte=4) | ||||
| >>> Article.objects.get_count() | ||||
| 4L | ||||
|  | ||||
| """ | ||||
|  | ||||
| from django.conf import settings | ||||
|   | ||||
| @@ -83,7 +83,7 @@ This is a test | ||||
| [This is a test, John's second story] | ||||
|  | ||||
| # The underlying query only makes one join when a related table is referenced twice. | ||||
| >>> null, sql, null = Article.objects._get_sql_clause(reporter__first_name__exact='John', reporter__last_name__exact='Smith') | ||||
| >>> null, sql, null = Article.objects._get_sql_clause(True, reporter__first_name__exact='John', reporter__last_name__exact='Smith') | ||||
| >>> sql.count('INNER JOIN') | ||||
| 1 | ||||
|  | ||||
| @@ -152,4 +152,9 @@ John Smith | ||||
| >>> Reporter.objects.get_list(articles__reporter__first_name__startswith='John', distinct=True) | ||||
| [John Smith] | ||||
|  | ||||
| # Delete requiring join is prohibited | ||||
| >>> Article.objects.delete(reporter__first_name__startswith='Jo') | ||||
| Traceback (most recent call last): | ||||
|     ... | ||||
| TypeError: Joins are not allowed in this type of query | ||||
| """ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user