Ejemplo n.º 1
0
    def delete(self, entity_instance):
        """Delete an entity instance"""
        from sqlalchemy.orm.session import Session

        session = Session.object_session(entity_instance)
        #
        # new and deleted instances cannot be deleted
        #
        if session:
            if entity_instance in session.new:
                session.expunge(entity_instance)
            elif (entity_instance not in session.deleted) and (
                entity_instance in session
            ):  # if the object is not in the session, it might allready be deleted
                history = None
                #
                # only if we know the primary key, we can keep track of its history
                #
                primary_key = self.mapper.primary_key_from_instance(entity_instance)
                #
                # we can only store history of objects where the primary key has only
                # 1 element
                # @todo: store history for compound primary keys
                #
                if not None in primary_key and len(primary_key) == 1:
                    pk = primary_key[0]
                    # save the state before the update
                    from camelot.model.memento import BeforeDelete

                    # only register the delete when the camelot model is active
                    if hasattr(BeforeDelete, "query"):
                        from camelot.model.authentication import getCurrentAuthentication

                        history = BeforeDelete(
                            model=unicode(self.entity.__name__),
                            primary_key=pk,
                            previous_attributes={},
                            authentication=getCurrentAuthentication(),
                        )
                entity_instance.delete()
                session.flush([entity_instance])
                if history:
                    Session.object_session(history).flush([history])
Ejemplo n.º 2
0
 def delete(self, entity_instance):
     """Delete an entity instance"""
     from sqlalchemy.orm.session import Session
     session = Session.object_session(entity_instance)
     #
     # new and deleted instances cannot be deleted
     #
     if session:
         if entity_instance in session.new:
             session.expunge(entity_instance)
         elif (entity_instance not in session.deleted) and \
              (entity_instance in session): # if the object is not in the session, it might allready be deleted
             history = None
             #
             # only if we know the primary key, we can keep track of its history
             #
             primary_key = self.mapper.primary_key_from_instance(
                 entity_instance)
             #
             # we can only store history of objects where the primary key has only
             # 1 element
             # @todo: store history for compound primary keys
             #
             if not None in primary_key and len(primary_key) == 1:
                 pk = primary_key[0]
                 # save the state before the update
                 from camelot.model.memento import BeforeDelete
                 # only register the delete when the camelot model is active
                 if hasattr(BeforeDelete, 'query'):
                     from camelot.model.authentication import getCurrentAuthentication
                     history = BeforeDelete(
                         model=unicode(self.entity.__name__),
                         primary_key=pk,
                         previous_attributes={},
                         authentication=getCurrentAuthentication())
             entity_instance.delete()
             session.flush([entity_instance])
             if history:
                 Session.object_session(history).flush([history])
Ejemplo n.º 3
0
    def _handle_update_requests(self):
        #
        # Copy the update requests and clear the list of requests
        #
        locker = QtCore.QMutexLocker(self._mutex)
        update_requests = [u for u in self._update_requests]
        self._update_requests = []
        locker.unlock()
        #
        # Handle the requests
        #
        for flushed, row, column, value in update_requests:
            attribute, field_attributes = self.getColumns()[column]

            from sqlalchemy.exceptions import DatabaseError
            from sqlalchemy import orm
            new_value = value()
            self.logger.debug( 'set data for row %s;col %s' % ( row, column ) )

            if new_value == ValueLoading:
                return None

            o = self._get_object( row )
            if not o:
                # the object might have been deleted from the collection while the editor
                # was still open
                self.logger.debug( 'this object is no longer in the collection' )
                try:
                    self.unflushed_rows.remove( row )
                except KeyError:
                    pass
                return

            old_value = getattr( o, attribute )
            #
            # When the value is a related object, the related object might have changed
            #
            changed = ( new_value != old_value ) or (
              field_attributes.get('embedded', False) and \
              field_attributes.get('target', False))
            #
            # In case the attribute is a OneToMany or ManyToMany, we cannot simply compare the
            # old and new value to know if the object was changed, so we'll
            # consider it changed anyway
            #
            direction = field_attributes.get( 'direction', None )
            if direction in ( orm.interfaces.MANYTOMANY, orm.interfaces.ONETOMANY ):
                changed = True
            if changed:
                # update the model
                model_updated = False
                try:
                    setattr( o, attribute, new_value )
                    #
                    # setting this attribute, might trigger a default function to return a value,
                    # that was not returned before
                    #
                    self.admin.set_defaults( o, include_nullable_fields=False )
                    model_updated = True
                except AttributeError, e:
                    self.logger.error( u"Can't set attribute %s to %s" % ( attribute, unicode( new_value ) ), exc_info = e )
                except TypeError:
                    # type error can be raised in case we try to set to a collection
                    pass
                if self.flush_changes and self.validator.isValid( row ):
                    # save the state before the update
                    try:
                        self.admin.flush( o )
                    except DatabaseError, e:
                        #@todo: when flushing fails, the object should not be removed from the unflushed rows ??
                        self.logger.error( 'Programming Error, could not flush object', exc_info = e )
                    locker.relock()
                    try:
                        self.unflushed_rows.remove( row )
                    except KeyError:
                        pass
                    locker.unlock()
                    #
                    # we can only track history if the model was updated, and it was
                    # flushed before, otherwise it has no primary key yet
                    #
                    if model_updated and hasattr(o, 'id') and o.id:
                        #
                        # in case of images or relations, we cannot pickle them
                        #
                        if ( not 'Imag' in old_value.__class__.__name__ ) and not direction:
                            from camelot.model.memento import BeforeUpdate
                            # only register the update when the camelot model is active
                            if hasattr(BeforeUpdate, 'query'):
                                from camelot.model.authentication import getCurrentAuthentication
                                history = BeforeUpdate( model = unicode( self.admin.entity.__name__ ),
                                                       primary_key = o.id,
                                                       previous_attributes = {attribute:old_value},
                                                       authentication = getCurrentAuthentication() )

                                try:
                                    history.flush()
                                except DatabaseError, e:
                                    self.logger.error( 'Programming Error, could not flush history', exc_info = e )
Ejemplo n.º 4
0
    def _handle_update_requests(self):
        #
        # Copy the update requests and clear the list of requests
        #
        locker = QtCore.QMutexLocker(self._mutex)
        update_requests = [u for u in self._update_requests]
        self._update_requests = []
        locker.unlock()
        #
        # Handle the requests
        #
        for flushed, row, column, value in update_requests:
            attribute, field_attributes = self.getColumns()[column]

            from sqlalchemy.exceptions import DatabaseError
            from sqlalchemy import orm
            new_value = value()
            self.logger.debug('set data for row %s;col %s' % (row, column))

            if new_value == ValueLoading:
                return None

            o = self._get_object(row)
            if not o:
                # the object might have been deleted from the collection while the editor
                # was still open
                self.logger.debug('this object is no longer in the collection')
                try:
                    self.unflushed_rows.remove(row)
                except KeyError:
                    pass
                return

            old_value = getattr(o, attribute)
            #
            # When the value is a related object, the related object might have changed
            #
            changed = ( new_value != old_value ) or (
              field_attributes.get('embedded', False) and \
              field_attributes.get('target', False))
            #
            # In case the attribute is a OneToMany or ManyToMany, we cannot simply compare the
            # old and new value to know if the object was changed, so we'll
            # consider it changed anyway
            #
            direction = field_attributes.get('direction', None)
            if direction in (orm.interfaces.MANYTOMANY,
                             orm.interfaces.ONETOMANY):
                changed = True
            if changed:
                # update the model
                model_updated = False
                try:
                    setattr(o, attribute, new_value)
                    #
                    # setting this attribute, might trigger a default function to return a value,
                    # that was not returned before
                    #
                    self.admin.set_defaults(o, include_nullable_fields=False)
                    model_updated = True
                except AttributeError, e:
                    self.logger.error(u"Can't set attribute %s to %s" %
                                      (attribute, unicode(new_value)),
                                      exc_info=e)
                except TypeError:
                    # type error can be raised in case we try to set to a collection
                    pass
                if self.flush_changes and self.validator.isValid(row):
                    # save the state before the update
                    try:
                        self.admin.flush(o)
                    except DatabaseError, e:
                        #@todo: when flushing fails, the object should not be removed from the unflushed rows ??
                        self.logger.error(
                            'Programming Error, could not flush object',
                            exc_info=e)
                    locker.relock()
                    try:
                        self.unflushed_rows.remove(row)
                    except KeyError:
                        pass
                    locker.unlock()
                    #
                    # we can only track history if the model was updated, and it was
                    # flushed before, otherwise it has no primary key yet
                    #
                    if model_updated and hasattr(o, 'id') and o.id:
                        #
                        # in case of images or relations, we cannot pickle them
                        #
                        if (not 'Imag' in old_value.__class__.__name__
                            ) and not direction:
                            from camelot.model.memento import BeforeUpdate
                            # only register the update when the camelot model is active
                            if hasattr(BeforeUpdate, 'query'):
                                from camelot.model.authentication import getCurrentAuthentication
                                history = BeforeUpdate(
                                    model=unicode(self.admin.entity.__name__),
                                    primary_key=o.id,
                                    previous_attributes={attribute: old_value},
                                    authentication=getCurrentAuthentication())

                                try:
                                    history.flush()
                                except DatabaseError, e:
                                    self.logger.error(
                                        'Programming Error, could not flush history',
                                        exc_info=e)