Changeset 8267
- Timestamp:
- 08/09/08 12:19:23 (4 months ago)
- Files:
-
- django/trunk/django/db/models/base.py (modified) (4 diffs)
- django/trunk/django/db/models/query.py (modified) (2 diffs)
- django/trunk/django/db/models/sql/subqueries.py (modified) (1 diff)
- django/trunk/docs/db-api.txt (modified) (1 diff)
- django/trunk/tests/modeltests/force_insert_update (added)
- django/trunk/tests/modeltests/force_insert_update/__init__.py (added)
- django/trunk/tests/modeltests/force_insert_update/models.py (added)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/trunk/django/db/models/base.py
r8244 r8267 18 18 from django.db.models.query import delete_objects, Q, CollectedObjects 19 19 from django.db.models.options import Options 20 from django.db import connection, transaction 20 from django.db import connection, transaction, DatabaseError 21 21 from django.db.models import signals 22 22 from django.db.models.loading import register_models, get_model … … 269 269 pk = property(_get_pk_val, _set_pk_val) 270 270 271 def save(self ):271 def save(self, force_insert=False, force_update=False): 272 272 """ 273 273 Saves the current instance. Override this in a subclass if you want to 274 274 control the saving process. 275 """ 276 self.save_base() 275 276 The 'force_insert' and 'force_update' parameters can be used to insist 277 that the "save" must be an SQL insert or update (or equivalent for 278 non-SQL backends), respectively. Normally, they should not be set. 279 """ 280 if force_insert and force_update: 281 raise ValueError("Cannot force both insert and updating in " 282 "model saving.") 283 self.save_base(force_insert=force_insert, force_update=force_update) 277 284 278 285 save.alters_data = True 279 286 280 def save_base(self, raw=False, cls=None): 287 def save_base(self, raw=False, cls=None, force_insert=False, 288 force_update=False): 281 289 """ 282 290 Does the heavy-lifting involved in saving. Subclasses shouldn't need to … … 285 293 ('raw' and 'cls'). 286 294 """ 295 assert not (force_insert and force_update) 287 296 if not cls: 288 297 cls = self.__class__ … … 320 329 if pk_set: 321 330 # Determine whether a record with the primary key already exists. 322 if manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by(): 331 if (force_update or (not force_insert and 332 manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by())): 323 333 # It does already exist, so do an UPDATE. 324 if non_pks:334 if force_update or non_pks: 325 335 values = [(f, None, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks] 326 manager.filter(pk=pk_val)._update(values) 336 rows = manager.filter(pk=pk_val)._update(values) 337 if force_update and not rows: 338 raise DatabaseError("Forced update did not affect any rows.") 327 339 else: 328 340 record_exists = False 329 341 if not pk_set or not record_exists: 330 342 if not pk_set: 343 if force_update: 344 raise ValueError("Cannot force an update in save() with no primary key.") 331 345 values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True))) for f in meta.local_fields if not isinstance(f, AutoField)] 332 346 else: django/trunk/django/db/models/query.py
r8223 r8267 400 400 query = self.query.clone(sql.UpdateQuery) 401 401 query.add_update_values(kwargs) 402 query.execute_sql(None)402 rows = query.execute_sql(None) 403 403 transaction.commit_unless_managed() 404 404 self._result_cache = None 405 return rows 405 406 update.alters_data = True 406 407 … … 416 417 query = self.query.clone(sql.UpdateQuery) 417 418 query.add_update_fields(values) 418 query.execute_sql(None)419 419 self._result_cache = None 420 return query.execute_sql(None) 420 421 _update.alters_data = True 421 422 django/trunk/django/db/models/sql/subqueries.py
r7835 r8267 110 110 111 111 def execute_sql(self, result_type=None): 112 super(UpdateQuery, self).execute_sql(result_type) 112 """ 113 Execute the specified update. Returns the number of rows affected by 114 the primary update query (there could be other updates on related 115 tables, but their rowcounts are not returned). 116 """ 117 cursor = super(UpdateQuery, self).execute_sql(result_type) 118 rows = cursor.rowcount 119 del cursor 113 120 for query in self.get_related_updates(): 114 121 query.execute_sql(result_type) 122 return rows 115 123 116 124 def as_sql(self): django/trunk/docs/db-api.txt
r8244 r8267 214 214 The one gotcha here is that you should be careful not to specify a primary-key 215 215 value explicitly when saving new objects, if you cannot guarantee the 216 primary-key value is unused. For more on this nuance, see 217 "Explicitly specifying auto-primary-key values" above. 216 primary-key value is unused. For more on this nuance, see `Explicitly 217 specifying auto-primary-key values`_ above and `Forcing an INSERT or UPDATE`_ 218 below. 219 220 Forcing an INSERT or UPDATE 221 ~~~~~~~~~~~~~~~~~~~~~~~~~~~ 222 223 **New in Django development version** 224 225 In some rare circumstances, it's necesary to be able to force the ``save()`` 226 method to perform an SQL ``INSERT`` and not fall back to doing an ``UPDATE``. 227 Or vice-versa: update, if possible, but not insert a new row. In these cases 228 you can pass the ``force_insert=True`` or ``force_update=True`` parameters to 229 the ``save()`` method. Passing both parameters is an error, since you cannot 230 both insert *and* update at the same time. 231 232 It should be very rare that you'll need to use these parameters. Django will 233 almost always do the right thing and trying to override that will lead to 234 errors that are difficult to track down. This feature is for advanced use 235 only. 218 236 219 237 Retrieving objects
