Exemple #1
0
    def update_view(self, user, view, **kwargs):
        """
        Updates an existing view instance.

        :param user: The user on whose behalf the view is updated.
        :type user: User
        :param view: The view instance that needs to be updated.
        :type view: View
        :param kwargs: The fields that need to be updated.
        :type kwargs: object
        :raises ValueError: When the provided view not an instance of View.
        :return: The updated view instance.
        :rtype: View
        """

        if not isinstance(view, View):
            raise ValueError('The view is not an instance of View.')

        group = view.table.database.group
        group.has_user(user, raise_error=True)

        view_type = view_type_registry.get_by_model(view)
        allowed_fields = ['name', 'filter_type', 'filters_disabled'
                          ] + view_type.allowed_fields
        view = set_allowed_attrs(kwargs, allowed_fields, view)
        view.save()

        view_updated.send(self, view=view, user=user)

        return view
    def update_view(self, user, view, **kwargs):
        """
        Updates an existing view instance.

        :param user: The user on whose behalf the view is updated.
        :type user: User
        :param view: The view instance that needs to be updated.
        :type view: View
        :param kwargs: The fields that need to be updated.
        :type kwargs: object
        :raises ValueError: When the provided view not an instance of View.
        :raises UserNotInGroupError: When the user does not belong to the related group.
        :return: The updated view instance.
        :rtype: View
        """

        if not isinstance(view, View):
            raise ValueError('The view is not an instance of View.')

        group = view.table.database.group
        if not group.has_user(user):
            raise UserNotInGroupError(user, group)

        view_type = view_type_registry.get_by_model(view)
        allowed_fields = ['name'] + view_type.allowed_fields
        view = set_allowed_attrs(kwargs, allowed_fields, view)
        view.save()

        return view
    def update_table(self, user, table, **kwargs):
        """
        Updates an existing table instance.

        :param user: The user on whose behalf the table is updated.
        :type user: User
        :param table: The table instance that needs to be updated.
        :type table: Table
        :param kwargs: The fields that need to be updated.
        :type kwargs: object
        :raises ValueError: When the provided table is not an instance of Table.
        :raises UserNotInGroupError: When the user does not belong to the related group.
        :return: The updated table instance.
        :rtype: Table
        """

        if not isinstance(table, Table):
            raise ValueError('The table is not an instance of Table')

        if not table.database.group.has_user(user):
            raise UserNotInGroupError(user, table.database.group)

        table = set_allowed_attrs(kwargs, ['name'], table)
        table.save()

        return table
Exemple #4
0
    def update_table(self, user, table, **kwargs):
        """
        Updates an existing table instance.

        :param user: The user on whose behalf the table is updated.
        :type user: User
        :param table: The table instance that needs to be updated.
        :type table: Table
        :param kwargs: The fields that need to be updated.
        :type kwargs: object
        :raises ValueError: When the provided table is not an instance of Table.
        :return: The updated table instance.
        :rtype: Table
        """

        if not isinstance(table, Table):
            raise ValueError("The table is not an instance of Table")

        table.database.group.has_user(user, raise_error=True)

        table = set_allowed_attrs(kwargs, ["name"], table)
        table.save()

        table_updated.send(self, table=table, user=user)

        return table
Exemple #5
0
def test_set_allowed_attrs():
    class Tmp(object):
        test_1 = None
        test_2 = None

    tmp1 = Tmp()
    tmp1 = set_allowed_attrs({
        "test_1": "test",
        "test_2": "test"
    }, ["test_1"], tmp1)

    assert tmp1.test_1 == "test"
    assert tmp1.test_2 is None
def test_set_allowed_attrs():
    class Tmp(object):
        test_1 = None
        test_2 = None

    tmp1 = Tmp()
    tmp1 = set_allowed_attrs({
        'test_1': 'test',
        'test_2': 'test'
    }, ['test_1'], tmp1)

    assert tmp1.test_1 == 'test'
    assert tmp1.test_2 is None
Exemple #7
0
    def update_field(self, user, field, new_type_name=None, **kwargs):
        """
        Updates the values of the given field, if provided it is also possible to change
        the type.

        :param user: The user on whose behalf the table is updated.
        :type user: User
        :param field: The field instance that needs to be updated.
        :type field: Field
        :param new_type_name: If the type needs to be changed it can be provided here.
        :type new_type_name: str
        :param kwargs: The field values that need to be updated
        :type kwargs: object
        :raises ValueError: When the provided field is not an instance of Field.
        :raises CannotChangeFieldType: When the database server responds with an
            error while trying to change the field type. This should rarely happen
            because of the lenient schema editor, which replaces the value with null
            if it ould not be converted.
        :return: The updated field instance.
        :rtype: Field
        """

        if not isinstance(field, Field):
            raise ValueError('The field is not an instance of Field.')

        group = field.table.database.group
        group.has_user(user, raise_error=True)

        old_field = deepcopy(field)
        field_type = field_type_registry.get_by_model(field)
        old_field_type = field_type
        from_model = field.table.get_model(field_ids=[], fields=[field])
        from_field_type = field_type.type

        # If the provided field type does not match with the current one we need to
        # migrate the field to the new type. Because the type has changed we also need
        # to remove all view filters.
        if new_type_name and field_type.type != new_type_name:
            field_type = field_type_registry.get(new_type_name)

            if field.primary and not field_type.can_be_primary_field:
                raise IncompatiblePrimaryFieldTypeError(new_type_name)

            new_model_class = field_type.model_class
            field.change_polymorphic_type_to(new_model_class)

            # If the field type changes it could be that some dependencies,
            # like filters or sortings need to be changed.
            ViewHandler().field_type_changed(field)

        allowed_fields = ['name'] + field_type.allowed_fields
        field_values = extract_allowed(kwargs, allowed_fields)

        field_values = field_type.prepare_values(field_values, user)
        before = field_type.before_update(old_field, field_values, user)

        field = set_allowed_attrs(field_values, allowed_fields, field)
        field.save()

        connection = connections[settings.USER_TABLE_DATABASE]

        # If no converter is found we are going to convert to field using the
        # lenient schema editor which will alter the field's type and set the data
        # value to null if it can't be converted.
        to_model = field.table.get_model(field_ids=[], fields=[field])
        from_model_field = from_model._meta.get_field(field.db_column)
        to_model_field = to_model._meta.get_field(field.db_column)

        # Before a field is updated we are going to call the before_schema_change
        # method of the old field because some cleanup of related instances might
        # need to happen.
        old_field_type.before_schema_change(old_field, field, from_model,
                                            to_model, from_model_field,
                                            to_model_field, user)

        # Try to find a data converter that can be applied.
        converter = field_converter_registry.find_applicable_converter(
            from_model, old_field, field)

        if converter:
            # If a field data converter is found we are going to use that one to alter
            # the field and maybe do some data conversion.
            converter.alter_field(old_field, field, from_model, to_model,
                                  from_model_field, to_model_field, user,
                                  connection)
        else:
            # If no field converter is found we are going to alter the field using the
            # the lenient schema editor.
            with lenient_schema_editor(
                    connection,
                    old_field_type.get_alter_column_prepare_old_value(
                        connection, old_field, field),
                    field_type.get_alter_column_prepare_new_value(
                        connection, old_field, field)) as schema_editor:
                try:
                    schema_editor.alter_field(from_model, from_model_field,
                                              to_model_field)
                except (ProgrammingError, DataError) as e:
                    # If something is going wrong while changing the schema we will
                    # just raise a specific exception. In the future we want to have
                    # some sort of converter abstraction where the values of certain
                    # types can be converted to another value.
                    logger.error(str(e))
                    message = f'Could not alter field when changing field type ' \
                              f'{from_field_type} to {new_type_name}.'
                    raise CannotChangeFieldType(message)

        from_model_field_type = from_model_field.db_parameters(
            connection)['type']
        to_model_field_type = to_model_field.db_parameters(connection)['type']
        altered_column = from_model_field_type != to_model_field_type

        # If the new field doesn't support select options we can delete those
        # relations.
        if (old_field_type.can_have_select_options
                and not field_type.can_have_select_options):
            old_field.select_options.all().delete()

        field_type.after_update(old_field, field, from_model, to_model, user,
                                connection, altered_column, before)

        field_updated.send(self, field=field, user=user)

        return field
Exemple #8
0
    def update_field(self, user, field, new_type_name=None, **kwargs):
        """
        Updates the values of the given field, if provided it is also possible to change
        the type.

        :param user: The user on whose behalf the table is updated.
        :type user: User
        :param field: The field instance that needs to be updated.
        :type field: Field
        :param new_type_name: If the type needs to be changed it can be provided here.
        :type new_type_name: str
        :param kwargs: The field values that need to be updated
        :type kwargs: object
        :raises ValueError: When the provided field is not an instance of Field.
        :raises UserNotInGroupError: When the user does not belong to the related group.
        :raises CannotChangeFieldType: When the database server responds with an
            error while trying to change the field type. This should rarely happen
            because of the lenient schema editor, which replaces the value with null
            if it ould not be converted.
        :return: The updated field instance.
        :rtype: Field
        """

        if not isinstance(field, Field):
            raise ValueError('The field is not an instance of Field.')

        group = field.table.database.group
        if not group.has_user(user):
            raise UserNotInGroupError(user, group)

        old_field = deepcopy(field)
        field_type = field_type_registry.get_by_model(field)
        from_model = field.table.get_model(field_ids=[], fields=[field])
        from_field_type = field_type.type

        # If the provided field type does not match with the current one we need to
        # migrate the field to the new type.
        if new_type_name and field_type.type != new_type_name:
            field_type = field_type_registry.get(new_type_name)
            new_model_class = field_type.model_class
            field.change_polymorphic_type_to(new_model_class)

        allowed_fields = ['name'] + field_type.allowed_fields
        field = set_allowed_attrs(kwargs, allowed_fields, field)
        field.save()

        connection = connections[settings.USER_TABLE_DATABASE]
        to_model = field.table.get_model(field_ids=[], fields=[field])
        from_model_field = from_model._meta.get_field(field.db_column)
        to_model_field = to_model._meta.get_field(field.db_column)

        # Change the field in the table schema.
        with lenient_schema_editor(
                connection,
                field_type.get_alter_column_type_function(
                    connection, field)) as schema_editor:
            try:
                schema_editor.alter_field(from_model, from_model_field,
                                          to_model_field)
            except (ProgrammingError, DataError):
                # If something is going wrong while changing the schema we will just
                # raise a specific exception. In the future we want to have some sort
                # of converter abstraction where the values of certain types can be
                # converted to another value.
                message = f'Could not alter field when changing field type ' \
                          f'{from_field_type} to {new_type_name}.'
                logger.error(message)
                raise CannotChangeFieldType(message)

        from_model_field_type = from_model_field.db_parameters(
            connection)['type']
        to_model_field_type = to_model_field.db_parameters(connection)['type']
        altered_column = from_model_field_type != to_model_field_type

        field_type.after_update(field, old_field, to_model, from_model,
                                connection, altered_column)

        return field