def save_using_connection(instance, connection, force_insert=False, force_update=False, raw=False): model = instance.__class__ cls = instance.__class__ meta = cls._meta origin = cls if not meta.proxy: non_pks = [f for f in meta.local_fields if not f.primary_key] # First, try an UPDATE. If that doesn't update anything, do an INSERT. pk_val = instance._get_pk_val(meta) pk_set = pk_val is not None record_exists = True manager = cls._base_manager if pk_set: # Determine whether a record with the primary key already exists. if (force_update or (not force_insert and manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by())): # It does already exist, so do an UPDATE. if force_update or non_pks: values = [(f, None, (raw and getattr(instance, f.attname) or f.pre_save(instance, False))) for f in non_pks] q = manager.filter(pk=pk_val) q.query.connection = connection rows = q._update(values) if force_update and not rows: raise DatabaseError("Forced update did not affect any rows.") else: record_exists = False if not pk_set or not record_exists: if not pk_set: if force_update: raise ValueError("Cannot force an update in save() with no primary key.") values = [(f, f.get_db_prep_save(raw and getattr(instance, f.attname) or f.pre_save(instance, True))) for f in meta.local_fields if not isinstance(f, AutoField)] else: values = [(f, f.get_db_prep_save(raw and getattr(instance, f.attname) or f.pre_save(instance, True))) for f in meta.local_fields] if meta.order_with_respect_to: field = meta.order_with_respect_to values.append((meta.get_field_by_name('_order')[0], manager.filter(**{field.name: getattr(instance, field.attname)}).count())) record_exists = False update_pk = bool(meta.has_auto_field and not pk_set) if values: # Create a new record. result = _insert(model, connection, values, return_id=update_pk) else: # Create a new record with defaults for everything. result = _insert(model, connection, [(meta.pk, connection.ops.pk_default_value())], return_id=update_pk, raw_values=True) if update_pk: setattr(instance, meta.pk.attname, result)