def delete(self, request, view_sort_id): """Deletes an existing sort if the user belongs to the group.""" view = ViewHandler().get_sort(request.user, view_sort_id) ViewHandler().delete_sort(request.user, view) return Response(status=204)
def test_get_view(data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() grid = data_fixture.create_grid_view(user=user) handler = ViewHandler() with pytest.raises(ViewDoesNotExist): handler.get_view(user=user, view_id=99999) with pytest.raises(UserNotInGroupError): handler.get_view(user=user_2, view_id=grid.id) view = handler.get_view(user=user, view_id=grid.id) assert view.id == grid.id assert view.name == grid.name assert view.filter_type == 'AND' assert not view.filters_disabled assert isinstance(view, View) view = handler.get_view(user=user, view_id=grid.id, view_model=GridView) assert view.id == grid.id assert view.name == grid.name assert view.filter_type == 'AND' assert not view.filters_disabled assert isinstance(view, GridView) # If the error is raised we know for sure that the query has resolved. with pytest.raises(AttributeError): handler.get_view( user=user, view_id=grid.id, base_queryset=View.objects.prefetch_related('UNKNOWN'))
def test_update_view(data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() table = data_fixture.create_database_table(user=user) grid = data_fixture.create_grid_view(table=table) handler = ViewHandler() with pytest.raises(UserNotInGroupError): handler.update_view(user=user_2, view=grid, name='Test 1') with pytest.raises(ValueError): handler.update_view(user=user, view=object(), name='Test 1') handler.update_view(user=user, view=grid, name='Test 1') grid.refresh_from_db() assert grid.name == 'Test 1' assert grid.filter_type == 'AND' assert not grid.filters_disabled handler.update_view(user=user, view=grid, filter_type='OR', filters_disabled=True) grid.refresh_from_db() assert grid.filter_type == 'OR' assert grid.filters_disabled
def fill_example_table_data(self, user, table): """ Fills the table with some initial example data. A new table is expected that already has the a primary field named 'name'. :param user: The user on whose behalf the table is filled. :type: user: User :param table: The table that needs the initial data. :type table: User """ view_handler = ViewHandler() field_handler = FieldHandler() view = view_handler.create_view(user, table, GridViewType.type, name='Grid') notes = field_handler.create_field(user, table, LongTextFieldType.type, name='Notes') active = field_handler.create_field(user, table, BooleanFieldType.type, name='Active') field_options = { notes.id: {'width': 400}, active.id: {'width': 100} } fields = [notes, active] view_handler.update_grid_view_field_options(view, field_options, fields=fields) model = table.get_model(attribute_names=True) model.objects.create(name='Tesla', active=True) model.objects.create(name='Amazon', active=False)
def test_single_select_field_type_get_order(data_fixture): user = data_fixture.create_user() database = data_fixture.create_database_application(user=user, name='Placeholder') table = data_fixture.create_database_table(name='Example', database=database) field = data_fixture.create_single_select_field(table=table) option_c = data_fixture.create_select_option(field=field, value='C', color='blue') option_a = data_fixture.create_select_option(field=field, value='A', color='blue') option_b = data_fixture.create_select_option(field=field, value='B', color='blue') grid_view = data_fixture.create_grid_view(table=table) view_handler = ViewHandler() row_handler = RowHandler() row_1 = row_handler.create_row(user=user, table=table, values={f'field_{field.id}': option_b.id}) row_2 = row_handler.create_row(user=user, table=table, values={f'field_{field.id}': option_a.id}) row_3 = row_handler.create_row(user=user, table=table, values={f'field_{field.id}': option_c.id}) row_4 = row_handler.create_row(user=user, table=table, values={f'field_{field.id}': option_b.id}) row_5 = row_handler.create_row(user=user, table=table, values={f'field_{field.id}': None}) sort = data_fixture.create_view_sort(view=grid_view, field=field, order='ASC') model = table.get_model() rows = view_handler.apply_sorting(grid_view, model.objects.all()) row_ids = [row.id for row in rows] assert row_ids == [row_5.id, row_2.id, row_1.id, row_4.id, row_3.id] sort.order = 'DESC' sort.save() rows = view_handler.apply_sorting(grid_view, model.objects.all()) row_ids = [row.id for row in rows] assert row_ids == [row_3.id, row_1.id, row_4.id, row_2.id, row_5.id] option_a.value = 'Z' option_a.save() sort.order = 'ASC' sort.save() model = table.get_model() rows = view_handler.apply_sorting(grid_view, model.objects.all()) row_ids = [row.id for row in rows] assert row_ids == [row_5.id, row_1.id, row_4.id, row_3.id, row_2.id]
def test_get_filter(data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() equal_filter = data_fixture.create_view_filter(user=user) handler = ViewHandler() with pytest.raises(ViewFilterDoesNotExist): handler.get_filter(user=user, view_filter_id=99999) with pytest.raises(UserNotInGroupError): handler.get_filter(user=user_2, view_filter_id=equal_filter.id) with pytest.raises(AttributeError): handler.get_filter( user=user, view_filter_id=equal_filter.id, base_queryset=ViewFilter.objects.prefetch_related('UNKNOWN')) filter = handler.get_filter(user=user, view_filter_id=equal_filter.id) assert filter.id == equal_filter.id assert filter.view_id == equal_filter.view_id assert filter.field_id == equal_filter.field_id assert filter.type == equal_filter.type assert filter.value == equal_filter.value
def test_get_sort(data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() equal_sort = data_fixture.create_view_sort(user=user) handler = ViewHandler() with pytest.raises(ViewSortDoesNotExist): handler.get_sort(user=user, view_sort_id=99999) with pytest.raises(UserNotInGroupError): handler.get_sort(user=user_2, view_sort_id=equal_sort.id) with pytest.raises(AttributeError): handler.get_sort( user=user, view_sort_id=equal_sort.id, base_queryset=ViewSort.objects.prefetch_related('UNKNOWN')) sort = handler.get_sort(user=user, view_sort_id=equal_sort.id) assert sort.id == equal_sort.id assert sort.view_id == equal_sort.view_id assert sort.field_id == equal_sort.field_id assert sort.order == equal_sort.order
def get(self, request, view_id, field_options): """ Lists all the rows of a grid view, paginated either by a page or offset/limit. If the limit get parameter is provided the limit/offset pagination will be used else the page number pagination. Optionally the field options can also be included in the response if the the `field_options` are provided in the include GET parameter. """ search = request.GET.get('search') view_handler = ViewHandler() view = view_handler.get_view(view_id, GridView) view.table.database.group.has_user(request.user, raise_error=True, allow_if_template=True) model = view.table.get_model() queryset = model.objects.all().enhance_by_fields() # Applies the view filters and sortings to the queryset if there are any. queryset = view_handler.apply_filters(view, queryset) queryset = view_handler.apply_sorting(view, queryset) if search: queryset = queryset.search_all_fields(search) if 'count' in request.GET: return Response({'count': queryset.count()}) if LimitOffsetPagination.limit_query_param in request.GET: paginator = LimitOffsetPagination() else: paginator = PageNumberPagination() page = paginator.paginate_queryset(queryset, request, self) serializer_class = get_row_serializer_class(model, RowSerializer, is_response=True) serializer = serializer_class(page, many=True) response = paginator.get_paginated_response(serializer.data) if field_options: # The serializer has the GridViewFieldOptionsField which fetches the # field options from the database and creates them if they don't exist, # but when added to the context the fields don't have to be fetched from # the database again when checking if they exist. context = { 'fields': [o['field'] for o in model._field_objects.values()] } serialized_view = GridViewSerializer(view, context=context).data response.data['field_options'] = serialized_view['field_options'] return response
def test_update_view(send_mock, data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() table = data_fixture.create_database_table(user=user) grid = data_fixture.create_grid_view(table=table) handler = ViewHandler() with pytest.raises(UserNotInGroupError): handler.update_view(user=user_2, view=grid, name='Test 1') with pytest.raises(ValueError): handler.update_view(user=user, view=object(), name='Test 1') view = handler.update_view(user=user, view=grid, name='Test 1') send_mock.assert_called_once() assert send_mock.call_args[1]['view'].id == view.id assert send_mock.call_args[1]['user'].id == user.id grid.refresh_from_db() assert grid.name == 'Test 1' assert grid.filter_type == 'AND' assert not grid.filters_disabled handler.update_view(user=user, view=grid, filter_type='OR', filters_disabled=True) grid.refresh_from_db() assert grid.filter_type == 'OR' assert grid.filters_disabled
def test_create_view(send_mock, data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() table = data_fixture.create_database_table(user=user) table_2 = data_fixture.create_database_table(user=user) handler = ViewHandler() view = handler.create_view(user=user, table=table, type_name='grid', name='Test grid') send_mock.assert_called_once() assert send_mock.call_args[1]['view'].id == view.id assert send_mock.call_args[1]['user'].id == user.id assert View.objects.all().count() == 1 assert GridView.objects.all().count() == 1 grid = GridView.objects.all().first() assert grid.name == 'Test grid' assert grid.order == 1 assert grid.table == table assert grid.filter_type == 'AND' assert not grid.filters_disabled handler.create_view(user=user, table=table, type_name='grid', name='Something else', filter_type='OR', filters_disabled=True) assert View.objects.all().count() == 2 assert GridView.objects.all().count() == 2 grid = GridView.objects.all().last() assert grid.name == 'Something else' assert grid.order == 2 assert grid.table == table assert grid.filter_type == 'OR' assert grid.filters_disabled grid = handler.create_view(user=user, table=table_2, type_name='grid', name='Name', filter_type='OR', filters_disabled=False) assert View.objects.all().count() == 3 assert GridView.objects.all().count() == 3 assert grid.name == 'Name' assert grid.order == 1 assert grid.table == table_2 assert grid.filter_type == 'OR' assert not grid.filters_disabled with pytest.raises(UserNotInGroupError): handler.create_view(user=user_2, table=table, type_name='grid', name='') with pytest.raises(ViewTypeDoesNotExist): handler.create_view(user=user, table=table, type_name='UNKNOWN', name='')
def post(self, request, data, view_id): """Creates a new sort for the provided view.""" view_handler = ViewHandler() view = view_handler.get_view(request.user, view_id) # We can safely assume the field exists because the CreateViewSortSerializer # has already checked that. field = Field.objects.get(pk=data['field']) view_sort = view_handler.create_sort(request.user, view, field, data['order']) serializer = ViewSortSerializer(view_sort) return Response(serializer.data)
def post(self, request, data, view_id): """Creates a new filter for the provided view.""" view_handler = ViewHandler() view = view_handler.get_view(request.user, view_id) # We can safely assume the field exists because the CreateViewFilterSerializer # has already checked that. field = Field.objects.get(pk=data['field']) view_filter = view_handler.create_filter(request.user, view, field, data['type'], data['value']) serializer = ViewFilterSerializer(view_filter) return Response(serializer.data)
def test_create_view(data_fixture): user = data_fixture.create_user() user_2 = data_fixture.create_user() table = data_fixture.create_database_table(user=user) handler = ViewHandler() handler.create_view(user=user, table=table, type_name='grid', name='Test grid') assert View.objects.all().count() == 1 assert GridView.objects.all().count() == 1 grid = GridView.objects.all().first() assert grid.name == 'Test grid' assert grid.order == 1 assert grid.table == table with pytest.raises(UserNotInGroupError): handler.create_view(user=user_2, table=table, type_name='grid', name='') with pytest.raises(ViewTypeDoesNotExist): handler.create_view(user=user, table=table, type_name='UNKNOWN', name='')
def patch(self, request, view_id): """Updates the view if the user belongs to the group.""" view = ViewHandler().get_view(request.user, view_id).specific view_type = view_type_registry.get_by_model(view) data = validate_data_custom_fields( view_type.type, view_type_registry, request.data, base_serializer_class=UpdateViewSerializer ) view = ViewHandler().update_view(request.user, view, **data) serializer = view_type_registry.get_serializer(view, ViewSerializer) return Response(serializer.data)
def patch(self, request, data, view_sort_id): """Updates the view sort if the user belongs to the group.""" handler = ViewHandler() view_sort = handler.get_sort(request.user, view_sort_id) if 'field' in data: # We can safely assume the field exists because the # UpdateViewSortSerializer has already checked that. data['field'] = Field.objects.get(pk=data['field']) view_sort = handler.update_sort(request.user, view_sort, **data) serializer = ViewSortSerializer(view_sort) return Response(serializer.data)
def test_update_grid_view_field_options(data_fixture): user = data_fixture.create_user() table = data_fixture.create_database_table(user=user) grid_view = data_fixture.create_grid_view(table=table) field_1 = data_fixture.create_text_field(table=table) field_2 = data_fixture.create_text_field(table=table) field_3 = data_fixture.create_text_field() with pytest.raises(ValueError): ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={ 'strange_format': {'height': 150}, }) with pytest.raises(UnrelatedFieldError): ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={ 99999: {'width': 150}, }) with pytest.raises(UnrelatedFieldError): ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={ field_3.id: {'width': 150}, }) ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={ str(field_1.id): {'width': 150}, field_2.id: {'width': 250} }) options_4 = grid_view.get_field_options() assert len(options_4) == 2 assert options_4[0].width == 150 assert options_4[0].field_id == field_1.id assert options_4[1].width == 250 assert options_4[1].field_id == field_2.id field_4 = data_fixture.create_text_field(table=table) ViewHandler().update_grid_view_field_options(grid_view=grid_view, field_options={ field_2.id: {'width': 300}, field_4.id: {'width': 50} }) options_4 = grid_view.get_field_options() assert len(options_4) == 3 assert options_4[0].width == 150 assert options_4[0].field_id == field_1.id assert options_4[1].width == 300 assert options_4[1].field_id == field_2.id assert options_4[2].width == 50 assert options_4[2].field_id == field_4.id
def fill_initial_table_data(self, user, table, fields, data, model): """ Fills the provided table with the normalized data that needs to be created upon creation of the table. :param user: The user on whose behalf the table is created. :type user: User` :param table: The newly created table where the initial data has to be inserted into. :type table: Table :param fields: A list containing the field names. :type fields: list :param data: A list containing the rows that need to be inserted. :type data: list :param model: The generated table model of the table that needs to be filled with initial data. :type model: TableModel """ ViewHandler().create_view(user, table, GridViewType.type, name='Grid') bulk_data = [ model(**{ f'field_{fields[index].id}': str(value) for index, value in enumerate(row) }) for row in data ] model.objects.bulk_create(bulk_data)
def patch(self, request, view_id, data): """ Updates the field options for the provided grid view. The following example body data will only update the width of the FIELD_ID and leaves the others untouched. { FIELD_ID: { 'width': 200 } } """ handler = ViewHandler() view = handler.get_view(request.user, view_id, GridView) handler.update_grid_view_field_options(view, data['field_options']) return Response(GridViewSerializer(view).data)
def get(self, request, view_id, filters, sortings): """Selects a single view and responds with a serialized version.""" view = ViewHandler().get_view(request.user, view_id) serializer = view_type_registry.get_serializer(view, ViewSerializer, filters=filters, sortings=sortings) return Response(serializer.data)
def get(self, request, view_id, filters, sortings): """Selects a single view and responds with a serialized version.""" view = ViewHandler().get_view(view_id) view.table.database.group.has_user(request.user, raise_error=True) serializer = view_type_registry.get_serializer( view, ViewSerializer, filters=filters, sortings=sortings ) return Response(serializer.data)
def patch(self, request, data, view_filter_id): """Updates the view filter if the user belongs to the group.""" handler = ViewHandler() view_filter = handler.get_filter(request.user, view_filter_id) if 'field' in data: # We can safely assume the field exists because the # UpdateViewFilterSerializer has already checked that. data['field'] = Field.objects.get(pk=data['field']) if 'type' in data: data['type_name'] = data.pop('type') view_filter = handler.update_filter(request.user, view_filter, **data) serializer = ViewFilterSerializer(view_filter) return Response(serializer.data)
def post(self, request, data, table_id): """Creates a new view for a user.""" table = TableHandler().get_table(request.user, table_id) view = ViewHandler().create_view( request.user, table, data.pop('type'), **data) serializer = view_type_registry.get_serializer(view, ViewSerializer) return Response(serializer.data)
def get(self, request, view_id): """ Responds with a list of serialized sortings that belong to the view if the user has access to that group. """ view = ViewHandler().get_view(request.user, view_id) sortings = ViewSort.objects.filter(view=view) serializer = ViewSortSerializer(sortings, many=True) return Response(serializer.data)
def post(self, request, data, table_id, filters, sortings): """Creates a new view for a user.""" table = TableHandler().get_table(table_id) view = ViewHandler().create_view(request.user, table, data.pop("type"), **data) serializer = view_type_registry.get_serializer( view, ViewSerializer, filters=filters, sortings=sortings ) return Response(serializer.data)
def get(self, request, view_id): """ Responds with a list of serialized filters that belong to the view if the user has access to that group. """ view = ViewHandler().get_view(view_id) view.table.database.group.has_user(request.user, raise_error=True) filters = ViewFilter.objects.filter(view=view) serializer = ViewFilterSerializer(filters, many=True) return Response(serializer.data)
def test_views_reordered(mock_broadcast_to_channel_group, data_fixture): user = data_fixture.create_user() view = data_fixture.create_grid_view(user=user) ViewHandler().order_views(user=user, table=view.table, order=[view.id]) mock_broadcast_to_channel_group.delay.assert_called_once() args = mock_broadcast_to_channel_group.delay.call_args assert args[0][0] == f"table-{view.table.id}" assert args[0][1]["type"] == "views_reordered" assert args[0][1]["table_id"] == view.table.id assert args[0][1]["order"] == [view.id]
def test_view_sort_updated(mock_broadcast_to_channel_group, data_fixture): user = data_fixture.create_user() view_sort = data_fixture.create_view_sort(user=user) view_sort = ViewHandler().update_sort(user=user, view_sort=view_sort, order="DESC") mock_broadcast_to_channel_group.delay.assert_called_once() args = mock_broadcast_to_channel_group.delay.call_args assert args[0][0] == f"table-{view_sort.view.table.id}" assert args[0][1]["type"] == "view_sort_updated" assert args[0][1]["view_sort_id"] == view_sort.id assert args[0][1]["view_sort"]["id"] == view_sort.id
def test_view_filter_updated(mock_broadcast_to_channel_group, data_fixture): user = data_fixture.create_user() view_filter = data_fixture.create_view_filter(user=user) view_filter = ViewHandler().update_filter(user=user, view_filter=view_filter, value='test2') mock_broadcast_to_channel_group.delay.assert_called_once() args = mock_broadcast_to_channel_group.delay.call_args assert args[0][0] == f'table-{view_filter.view.table.id}' assert args[0][1]['type'] == 'view_filter_updated' assert args[0][1]['view_filter_id'] == view_filter.id assert args[0][1]['view_filter']['id'] == view_filter.id
def test_view_sort_updated(mock_broadcast_to_channel_group, data_fixture): user = data_fixture.create_user() view_sort = data_fixture.create_view_sort(user=user) view_sort = ViewHandler().update_sort(user=user, view_sort=view_sort, order='DESC') mock_broadcast_to_channel_group.delay.assert_called_once() args = mock_broadcast_to_channel_group.delay.call_args assert args[0][0] == f'table-{view_sort.view.table.id}' assert args[0][1]['type'] == 'view_sort_updated' assert args[0][1]['view_sort_id'] == view_sort.id assert args[0][1]['view_sort']['id'] == view_sort.id
def test_view_created(mock_broadcast_to_channel_group, data_fixture): user = data_fixture.create_user() table = data_fixture.create_database_table(user=user) view = ViewHandler().create_view(user=user, table=table, type_name='grid', name='Grid') mock_broadcast_to_channel_group.delay.assert_called_once() args = mock_broadcast_to_channel_group.delay.call_args assert args[0][0] == f'table-{table.id}' assert args[0][1]['type'] == 'view_created' assert args[0][1]['view']['id'] == view.id assert 'filters' in args[0][1]['view'] assert 'sortings' in args[0][1]['view']