diff options
| author | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2008-01-28 14:27:53 +0000 |
|---|---|---|
| committer | Malcolm Tredinnick <malcolm.tredinnick@gmail.com> | 2008-01-28 14:27:53 +0000 |
| commit | de94d0cb9381bcab02b7be0de1d8ac577bcfab92 (patch) | |
| tree | 3ec57dad087e825dcb8c6d366ca74c786eb3a856 /django/db/models/sql/query.py | |
| parent | 911e65ada72d6faeecd156d285ac661058aa0f35 (diff) | |
queryset-refactor: Added an update method to QuerySets, since it's needed for
moving SQL out of the core code. Only direct fields and foreign keys can be
updated in this fashion, since multi-table updates are very non-portable.
This also cleans up the API for the UpdateQuery class a bit. Still need to
change DeleteQuery to work similarly, I suspect.
Refs #4260.
git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7043 bcc190cf-cafb-0310-a4f2-bffc1f526a37
Diffstat (limited to 'django/db/models/sql/query.py')
| -rw-r--r-- | django/db/models/sql/query.py | 49 |
1 files changed, 35 insertions, 14 deletions
diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index ee76523c3b..2f50fdfc98 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -174,6 +174,8 @@ class Query(object): obj.extra_params = self.extra_params[:] obj.extra_order_by = self.extra_order_by[:] obj.__dict__.update(kwargs) + if hasattr(obj, '_setup_query'): + obj._setup_query() return obj def results_iter(self): @@ -1159,6 +1161,12 @@ class UpdateQuery(Query): """ def __init__(self, *args, **kwargs): super(UpdateQuery, self).__init__(*args, **kwargs) + self._setup_query() + + def _setup_query(self): + """ + Run on initialisation and after cloning. + """ self.values = [] def as_sql(self): @@ -1166,22 +1174,24 @@ class UpdateQuery(Query): Creates the SQL for this query. Returns the SQL string and list of parameters. """ - assert len(self.tables) == 1, \ - "Can only update one table at a time." + self.select_related = False + self.pre_sql_setup() + if len(tables) != 1: + raise TypeError('Updates can only access a single database table at a time.') result = ['UPDATE %s' % self.tables[0]] result.append('SET') qn = self.quote_name_unless_alias - values = ['%s = %s' % (qn(v[0]), v[1]) for v in self.values] + values, update_params = [], [] + for name, val in self.values: + if val is not None: + values.append('%s = %%s' % qn(name)) + update_params.append(val) + else: + values.append('%s = NULL' % qn(name)) result.append(', '.join(values)) where, params = self.where.as_sql() result.append('WHERE %s' % where) - return ' '.join(result), tuple(params) - - def do_query(self, table, values, where): - self.tables = [table] - self.values = values - self.where = where - self.execute_sql(NONE) + return ' '.join(result), tuple(update_params + params) def clear_related(self, related_field, pk_list): """ @@ -1191,13 +1201,24 @@ class UpdateQuery(Query): This is used by the QuerySet.delete_objects() method. """ for offset in range(0, len(pk_list), GET_ITERATOR_CHUNK_SIZE): - where = self.where_class() + self.where = self.where_class() f = self.model._meta.pk - where.add((None, f.column, f, 'in', + self.where.add((None, f.column, f, 'in', pk_list[offset : offset + GET_ITERATOR_CHUNK_SIZE]), AND) - values = [(related_field.column, 'NULL')] - self.do_query(self.model._meta.db_table, values, where) + self.values = [(related_field.column, None)] + self.execute_sql(None) + + def add_update_values(self, values): + from django.db.models.base import Model + for name, val in values.items(): + field, direct, m2m = self.model._meta.get_field_by_name(name) + if not direct or m2m: + # Can only update non-relation fields and foreign keys. + raise TypeError('Cannot update model field %r (only non-relations and foreign keys permitted).' % field) + if field.rel and isinstance(val, Model): + val = val.pk + self.values.append((field.column, val)) class DateQuery(Query): """ |
