Example #1
0
 def _do_insert(self, manager, using, fields, update_pk, raw):
     """
     Do an INSERT. If update_pk is defined then this method should return
     the new pk for the model.
     """
     return manager._insert([self], fields=fields, return_id=update_pk,
                            using=using, raw=raw)
Example #2
0
    def save_base(self, raw=False, cls=None, origin=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', 'cls', and 'origin').
        """
        using = using or router.db_for_write(self.__class__, instance=self)
        connection = connections[using]
        assert not (force_insert and force_update)
        if cls is None:
            cls = self.__class__
            meta = cls._meta
            if not meta.proxy:
                origin = cls
        else:
            meta = cls._meta

        if origin and not meta.auto_created:
            signals.pre_save.send(sender=origin, instance=self, raw=raw)

        # 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.
        # We also go through this process to defer the save of proxy objects
        # to their actual underlying model.
        if not raw or meta.proxy:
            if meta.proxy:
                org = cls
            else:
                org = None
            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 field and 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(cls=parent, origin=org, using=using)

                if field:
                    setattr(self, field.attname, self._get_pk_val(parent._meta))
            if meta.proxy:
                return

        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 = self._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.using(using).filter(pk=pk_val).exists())):
                    # It does already exist, so do an UPDATE.
                    if force_update or non_pks:
                        values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
                        rows = manager.using(using).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 meta.order_with_respect_to:
                    # If this is a model with an order_with_respect_to
                    # autopopulate the _order field
                    field = meta.order_with_respect_to
                    order_value = manager.using(using).filter(**{field.name: getattr(self, field.attname)}).count()
                    setattr(self, '_order', order_value)

                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), connection=connection))
                        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), connection=connection))
                        for f in meta.local_fields]

                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, using=using)
                else:
                    # Create a new record with defaults for everything.
                    result = manager._insert([(meta.pk, connection.ops.pk_default_value())], return_id=update_pk, raw_values=True, using=using)

                if update_pk:
                    setattr(self, meta.pk.attname, result)
            transaction.commit_unless_managed(using=using)

        # Store the database on which the object was saved
        self._state.db = using
        # Once saved, this is no longer a to-be-added instance.
        self._state.adding = False

        # Signal that the save is complete
        if origin and not meta.auto_created:
            signals.post_save.send(sender=origin, instance=self,
                created=(not record_exists), raw=raw)
Example #3
0
    def save_base(self, raw=False, cls=None, origin=None, force_insert=False,
                  force_update=False, using=None, update_fields=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', 'cls', and 'origin').
        """
        using = using or router.db_for_write(self.__class__, instance=self)
        assert not (force_insert and (force_update or update_fields))
        assert update_fields is None or len(update_fields) > 0
        if cls is None:
            cls = self.__class__
            meta = cls._meta
            if not meta.proxy:
                origin = cls
        else:
            meta = cls._meta

        if origin and not meta.auto_created:
            signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using,
                                  update_fields=update_fields)

        # 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.
        # We also go through this process to defer the save of proxy objects
        # to their actual underlying model.
        if not raw or meta.proxy:
            if meta.proxy:
                org = cls
            else:
                org = None
            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 field and 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(cls=parent, origin=org, using=using,
                               update_fields=update_fields)

                if field:
                    setattr(self, field.attname, self._get_pk_val(parent._meta))
                    # Since we didn't have an instance of the parent handy, we
                    # set attname directly, bypassing the descriptor.
                    # Invalidate the related object cache, in case it's been
                    # accidentally populated. A fresh instance will be
                    # re-built from the database if necessary.
                    cache_name = field.get_cache_name()
                    if hasattr(self, cache_name):
                        delattr(self, cache_name)

            if meta.proxy:
                return

        if not meta.proxy:
            non_pks = [f for f in meta.local_fields if not f.primary_key]

            if update_fields:
                non_pks = [f for f in non_pks if f.name in update_fields or f.attname in update_fields]

            # 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._base_manager
            if pk_set:
                # Determine if we should do an update (pk already exists, forced update,
                # no force_insert)
                if ((force_update or update_fields) or (not force_insert and
                        manager.using(using).filter(pk=pk_val).exists())):
                    if force_update or non_pks:
                        values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
                        if values:
                            rows = manager.using(using).filter(pk=pk_val)._update(values)
                            if force_update and not rows:
                                raise DatabaseError("Forced update did not affect any rows.")
                            if update_fields and not rows:
                                raise DatabaseError("Save with update_fields did not affect any rows.")
                else:
                    record_exists = False
            if not pk_set or not record_exists:
                if meta.order_with_respect_to:
                    # If this is a model with an order_with_respect_to
                    # autopopulate the _order field
                    field = meta.order_with_respect_to
                    order_value = manager.using(using).filter(**{field.name: getattr(self, field.attname)}).count()
                    self._order = order_value

                fields = meta.local_fields
                if not pk_set:
                    if force_update or update_fields:
                        raise ValueError("Cannot force an update in save() with no primary key.")
                    fields = [f for f in fields if not isinstance(f, AutoField)]

                record_exists = False

                update_pk = bool(meta.has_auto_field and not pk_set)
                result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)

                if update_pk:
                    setattr(self, meta.pk.attname, result)
            transaction.commit_unless_managed(using=using)

        # Store the database on which the object was saved
        self._state.db = using
        # Once saved, this is no longer a to-be-added instance.
        self._state.adding = False

        # Signal that the save is complete
        if origin and not meta.auto_created:
            signals.post_save.send(sender=origin, instance=self, created=(not record_exists),
                                   update_fields=update_fields, raw=raw, using=using)
Example #4
0
    def save_base(self,
                  raw=False,
                  cls=None,
                  origin=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', 'cls', and 'origin').
        """
        using = using or router.db_for_write(self.__class__, instance=self)
        assert not (force_insert and force_update)
        if cls is None:
            cls = self.__class__
            meta = cls._meta
            if not meta.proxy:
                origin = cls
        else:
            meta = cls._meta

        if origin and not meta.auto_created:
            signals.pre_save.send(sender=origin,
                                  instance=self,
                                  raw=raw,
                                  using=using)

        # 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.
        # We also go through this process to defer the save of proxy objects
        # to their actual underlying model.
        if not raw or meta.proxy:
            if meta.proxy:
                org = cls
            else:
                org = None
            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 field and 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(cls=parent, origin=org, using=using)

                if field:
                    setattr(self, field.attname,
                            self._get_pk_val(parent._meta))
            if meta.proxy:
                return

        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 = self._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.using(using).filter(pk=pk_val).exists())):
                    # It does already exist, so do an UPDATE.
                    if force_update or non_pks:
                        values = [(f, None, (raw and getattr(self, f.attname)
                                             or f.pre_save(self, False)))
                                  for f in non_pks]
                        if values:
                            rows = manager.using(using).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 meta.order_with_respect_to:
                    # If this is a model with an order_with_respect_to
                    # autopopulate the _order field
                    field = meta.order_with_respect_to
                    order_value = manager.using(using).filter(
                        **{
                            field.name: getattr(self, field.attname)
                        }).count()
                    self._order = order_value

                fields = meta.local_fields
                if not pk_set:
                    if force_update:
                        raise ValueError(
                            "Cannot force an update in save() with no primary key."
                        )
                    fields = [
                        f for f in fields if not isinstance(f, AutoField)
                    ]

                record_exists = False

                update_pk = bool(meta.has_auto_field and not pk_set)
                result = manager._insert([self],
                                         fields=fields,
                                         return_id=update_pk,
                                         using=using,
                                         raw=raw)

                if update_pk:
                    setattr(self, meta.pk.attname, result)
            transaction.commit_unless_managed(using=using)

        # Store the database on which the object was saved
        self._state.db = using
        # Once saved, this is no longer a to-be-added instance.
        self._state.adding = False

        # Signal that the save is complete
        if origin and not meta.auto_created:
            signals.post_save.send(sender=origin,
                                   instance=self,
                                   created=(not record_exists),
                                   raw=raw,
                                   using=using)
Example #5
0
    def save_base(self,
                  raw=False,
                  cls=None,
                  force_insert=False,
                  force_update=False):
        """
        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

        # 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 field and 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(cls=parent)
                if field:
                    setattr(self, field.attname,
                            self._get_pk_val(parent._meta))
            if meta.proxy:
                return

        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 = self._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(self, f.attname)
                                             or f.pre_save(self, False)))
                                  for f in non_pks]
                        rows = manager.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)))
                        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)))
                        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)
                else:
                    # Create a new record with defaults for everything.
                    result = manager._insert(
                        [(meta.pk, connection.ops.pk_default_value())],
                        return_id=update_pk,
                        raw_values=True)

                if update_pk:
                    setattr(self, meta.pk.attname, result)
            transaction.commit_unless_managed()

        if signal:
            signals.post_save.send(sender=self.__class__,
                                   instance=self,
                                   created=(not record_exists),
                                   raw=raw)
Example #6
0
    def save_base(self, raw=False, cls=None, origin=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', 'cls', and 'origin').
        """
        using = using or router.db_for_write(self.__class__, instance=self)
        entity_exists = bool(not self._state.adding and self._original_pk == self.pk)
        assert not (force_insert and force_update)
        if cls is None:
            cls = self.__class__
            meta = cls._meta
            if not meta.proxy:
                origin = cls
        else:
            meta = cls._meta

        if origin and not meta.auto_created:
            signals.pre_save.send(sender=origin, instance=self, raw=raw, using=using)

        # 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.
        # We also go through this process to defer the save of proxy objects
        # to their actual underlying model.
        if not raw or meta.proxy:
            if meta.proxy:
                org = cls
            else:
                org = None
            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 field and 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(cls=parent, origin=org, using=using)

                if field:
                    setattr(self, field.attname, self._get_pk_val(parent._meta))
            if meta.proxy:
                return

        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 = self._get_pk_val(meta)
            pk_set = pk_val is not None
            record_exists = True
            manager = cls._base_manager
            connection = connections[using]

            # TODO/NONREL: Some backends could emulate force_insert/_update
            # with an optimistic transaction, but since it's costly we should
            # only do it when the user explicitly wants it.
            # By adding support for an optimistic locking transaction
            # in Django (SQL: SELECT ... FOR UPDATE) we could even make that
            # part fully reusable on all backends (the current .exists()
            # check below isn't really safe if you have lots of concurrent
            # requests. BTW, and neither is QuerySet.get_or_create).
            try_update = connection.features.distinguishes_insert_from_update
            if not try_update:
                record_exists = False

            if try_update and pk_set:
                # Determine whether a record with the primary key already exists.
                if (force_update or (not force_insert and
                        manager.using(using).filter(pk=pk_val).exists())):
                    # It does already exist, so do an UPDATE.
                    if force_update or non_pks:
                        values = [(f, None, (raw and getattr(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
                        if values:
                            rows = manager.using(using).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 meta.order_with_respect_to:
                    # If this is a model with an order_with_respect_to
                    # autopopulate the _order field
                    field = meta.order_with_respect_to
                    order_value = manager.using(using).filter(**{field.name: getattr(self, field.attname)}).count()
                    self._order = order_value

                fields = meta.local_fields
                if not pk_set:
                    if force_update:
                        raise ValueError("Cannot force an update in save() with no primary key.")
                    fields = [f for f in fields if not isinstance(f, AutoField)]

                record_exists = False

                update_pk = bool(meta.has_auto_field and not pk_set)
                result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)

                if update_pk:
                    setattr(self, meta.pk.attname, result)
            transaction.commit_unless_managed(using=using)

        # Store the database on which the object was saved
        self._state.db = using
        # Once saved, this is no longer a to-be-added instance.
        self._state.adding = False

        self._original_pk = self.pk

        # Signal that the save is complete
        if origin and not meta.auto_created:
            if connection.features.distinguishes_insert_from_update:
                created = not record_exists
            else:
                created = not entity_exists
            signals.post_save.send(sender=origin, instance=self,
                created=created, raw=raw, using=using)
Example #7
0
    def save_base(self,
                  raw=False,
                  cls=None,
                  origin=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', 'cls', and 'origin').
        """
        using = using or router.db_for_write(self.__class__, instance=self)
        connection = connections[using]
        assert not (force_insert and force_update)
        if cls is None:
            cls = self.__class__
            meta = cls._meta
            if not meta.proxy:
                origin = cls
        else:
            meta = cls._meta

        if origin and not meta.auto_created:
            signals.pre_save.send(sender=origin,
                                  instance=self,
                                  raw=raw,
                                  using=using)

        # 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.
        # We also go through this process to defer the save of proxy objects
        # to their actual underlying model.
        if not raw or meta.proxy:
            if meta.proxy:
                org = cls
            else:
                org = None
            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 field and 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(cls=parent, origin=org, using=using)

                if field:
                    setattr(self, field.attname,
                            self._get_pk_val(parent._meta))
            if meta.proxy:
                return

        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 = self._get_pk_val(meta)
            pk_set = pk_val is not None
            record_exists = True
            manager = cls._base_manager
            # TODO/NONREL: Some backends could emulate force_insert/_update
            # with an optimistic transaction, but since it's costly we should
            # only do it when the user explicitly wants it.
            # By adding support for an optimistic locking transaction
            # in Django (SQL: SELECT ... FOR UPDATE) we could even make that
            # part fully reusable on all backends (the current .exists()
            # check below isn't really safe if you have lots of concurrent
            # requests. BTW, and neither is QuerySet.get_or_create).
            try_update = connection.features.distinguishes_insert_from_update
            if not try_update:
                record_exists = False

            if try_update and pk_set:
                # Determine whether a record with the primary key already exists.
                if (force_update or
                    (not force_insert
                     and manager.using(using).filter(pk=pk_val).exists())):
                    # It does already exist, so do an UPDATE.
                    if force_update or non_pks:
                        values = [(f, None, (raw and getattr(self, f.attname)
                                             or f.pre_save(self, False)))
                                  for f in non_pks]
                        rows = manager.using(using).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 meta.order_with_respect_to:
                    # If this is a model with an order_with_respect_to
                    # autopopulate the _order field
                    field = meta.order_with_respect_to
                    order_value = manager.using(using).filter(
                        **{
                            field.name: getattr(self, field.attname)
                        }).count()
                    self._order = order_value

                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),
                                            connection=connection))
                        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),
                                            connection=connection))
                        for f in meta.local_fields
                    ]

                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,
                                             using=using)
                else:
                    # Create a new record with defaults for everything.
                    result = manager._insert(
                        [(meta.pk, connection.ops.pk_default_value())],
                        return_id=update_pk,
                        raw_values=True,
                        using=using)

                if update_pk:
                    setattr(self, meta.pk.attname, result)
            transaction.commit_unless_managed(using=using)

        # Store the database on which the object was saved
        self._state.db = using

        # Signal that the save is complete
        if origin and not meta.auto_created:
            signals.post_save.send(sender=origin,
                                   instance=self,
                                   created=(not record_exists),
                                   raw=raw,
                                   using=using)
Example #8
0
    def save_base(self, raw=False, cls=None, force_insert=False,
            force_update=False):
        """
        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

        # 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 field and 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(cls=parent)
                if field:
                    setattr(self, field.attname, self._get_pk_val(parent._meta))
            if meta.proxy:
                return

        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 = self._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(self, f.attname) or f.pre_save(self, False))) for f in non_pks]
                        rows = manager.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))) 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))) 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)
                else:
                    # Create a new record with defaults for everything.
                    result = manager._insert([(meta.pk, connection.ops.pk_default_value())], return_id=update_pk, raw_values=True)

                if update_pk:
                    setattr(self, meta.pk.attname, result)
            transaction.commit_unless_managed()

        if signal:
            signals.post_save.send(sender=self.__class__, instance=self,
                created=(not record_exists), raw=raw)
Example #9
0
    def save_base(self, raw=False, cls=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').
        """
        if not cls:
            cls = self.__class__
            meta = self._meta
            signal = True
            dispatcher.send(signal=signals.pre_save, sender=self.__class__,
                    instance=self, raw=raw)
        else:
            meta = cls._meta
            signal = False

        for parent, field in meta.parents.items():
            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)
        # Note: the comparison with '' is required for compatibility with
        # oldforms-style model creation.
        pk_set = pk_val is not None and smart_unicode(pk_val) != u''
        record_exists = True
        manager = cls._default_manager
        if pk_set:
            # Determine whether a record with the primary key already exists.
            if manager.filter(pk=pk_val).extra(select={'a': 1}).values('a').order_by():
                # It does already exist, so do an UPDATE.
                if non_pks:
                    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]
                    manager.filter(pk=pk_val)._update(values)
            else:
                record_exists = False
        if not pk_set or not record_exists:
            if not pk_set:
                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)]
            else:
                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 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)
            else:
                # Create a new record with defaults for everything.
                result = manager._insert([(meta.pk, connection.ops.pk_default_value())], return_id=update_pk, raw_values=True)

            if update_pk:
                setattr(self, meta.pk.attname, result)
        transaction.commit_unless_managed()

        if signal:
            dispatcher.send(signal=signals.post_save, sender=self.__class__,
                    instance=self, created=(not record_exists), raw=raw)
Example #10
0
                    order_value = manager.using(using).filter(**{field.name: getattr(self, field.attname)}).count()
                    self._order = order_value

                fields = meta.local_fields

                主键不存在又提供 force_update, 矛盾
                if not pk_set:
                    if force_update or update_fields:
                        raise ValueError("Cannot force an update in save() with no primary key.")
                    fields = [f for f in fields if not isinstance(f, AutoField)]

                只好执行插入操作
                record_exists = False

                update_pk = bool(meta.has_auto_field and not pk_set)
                result = manager._insert([self], fields=fields, return_id=update_pk, using=using, raw=raw)

                if update_pk:
                    setattr(self, meta.pk.attname, result)

            transaction.commit_unless_managed(using=using)


        self._state.db = using
        # Once saved, this is no longer a to-be-added instance.
        self._state.adding = False

        # Signal that the save is complete
        if origin and not meta.auto_created:
            signals.post_save.send(sender=origin, instance=self, created=(not record_exists),
                                   update_fields=update_fields, raw=raw, using=using)
Example #11
0
    def save_base(self, raw=False, cls=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').
        """
        if not cls:
            cls = self.__class__
            meta = self._meta
            signal = True
            dispatcher.send(signal=signals.pre_save,
                            sender=self.__class__,
                            instance=self,
                            raw=raw)
        else:
            meta = cls._meta
            signal = False

        # 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():
                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)
        # Note: the comparison with '' is required for compatibility with
        # oldforms-style model creation.
        pk_set = pk_val is not None and smart_unicode(pk_val) != u''
        record_exists = True
        manager = cls._default_manager
        if pk_set:
            # Determine whether a record with the primary key already exists.
            if manager.filter(pk=pk_val).extra(select={
                    'a': 1
            }).values('a').order_by():
                # It does already exist, so do an UPDATE.
                if non_pks:
                    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
                    ]
                    manager.filter(pk=pk_val)._update(values)
            else:
                record_exists = False
        if not pk_set or not record_exists:
            if not pk_set:
                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)]
            else:
                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 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)
            else:
                # Create a new record with defaults for everything.
                result = manager._insert(
                    [(meta.pk, connection.ops.pk_default_value())],
                    return_id=update_pk,
                    raw_values=True)

            if update_pk:
                setattr(self, meta.pk.attname, result)
        transaction.commit_unless_managed()

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