Beispiel #1
0
 def using(self, dbname, *args, **kwargs):
     from django.db import get_connection
     return self.get_query_set_by_connection(get_connection(dbname))
Beispiel #2
0
    def save_base(self, raw=False, cls=None, force_insert=False,
            force_update=False, using=None):
        """
        Does the heavy-lifting involved in saving. Subclasses shouldn't need to
        override this method. It's separate from save() in order to hide the
        need for overrides of save() to pass around internal-only parameters
        ('raw' and 'cls').
        """
        assert not (force_insert and force_update)
        if not cls:
            cls = self.__class__
            meta = self._meta
            signal = True
            signals.pre_save.send(sender=self.__class__, instance=self, raw=raw)
        else:
            meta = cls._meta
            signal = False

        # get model's connection
        from django.db import get_current_connection, get_connection
        if using:
            conn = get_connection(using)
        else:
            if hasattr(self,'__connection__'):
                conn = self.__connection__ 
            elif meta.using:
                conn = get_connection(meta.using)
            else:
                conn = get_current_connection()
        # If we are in a raw save, save the object exactly as presented.
        # That means that we don't try to be smart about saving attributes
        # that might have come from the parent class - we just save the
        # attributes we have been given to the class we have been given.
        if not raw:
            for parent, field in meta.parents.items():
                # At this point, parent's primary key field may be unknown
                # (for example, from administration form which doesn't fill
                # this field). If so, fill it.
                if getattr(self, parent._meta.pk.attname) is None and getattr(self, field.attname) is not None:
                    setattr(self, parent._meta.pk.attname, getattr(self, field.attname))

                self.save_base(raw, parent)
                setattr(self, field.attname, self._get_pk_val(parent._meta))

        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 = self._get_pk_val(meta)
        pk_set = pk_val is not None
        record_exists = True
        manager = cls._default_manager
        if pk_set:
            # Determine whether a record with the primary key already exists.
            if (force_update or (not force_insert and
                    manager.get_query_set_by_connection(conn).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, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, False), conn)) for f in non_pks]
                    rows = manager.get_query_set_by_connection(conn).filter(pk=pk_val)._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(self, f.attname) or f.pre_save(self, True), conn)) for f in meta.local_fields if not isinstance(f, AutoField)]
            else:
                values = [(f, f.get_db_prep_save(raw and getattr(self, f.attname) or f.pre_save(self, True), conn)) 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(self, field.attname)}).count()))
            record_exists = False

            update_pk = bool(meta.has_auto_field and not pk_set)
            if values:
                # Create a new record.
                result = manager._insert(values, return_id=update_pk, connection=conn)
            else:
                # Create a new record with defaults for everything.
                result = manager._insert([(meta.pk, conn.ops.pk_default_value())], return_id=update_pk, raw_values=True, connection=conn)

            if update_pk:
                setattr(self, meta.pk.attname, result)
        transaction.commit_unless_managed(conn) # need by connection

        if signal:
            signals.post_save.send(sender=self.__class__, instance=self,
                created=(not record_exists), raw=raw)