def test_below_limit_ok(self): test_list = self.pk_list[:999] qs = Delivery.objects.all().filter(pk__in=test_list) qs.count() qs = filter_qs_by_pk_list(Delivery.objects.all(), test_list) qs.count()
def test_volume_filtering_non_sqlite(self): result_qs = filter_qs_by_pk_list(Delivery.objects.all(), self.pk_list) self.assertEqual(result_qs.count(), VOLUME_TEST_MAX) self.assertEqual( set(result_qs.values_list('pk', flat=True)), set(Delivery.objects.all().values_list('pk', flat=True)), )
def test_limit_reached_mocked(self, mock_max_params): mock_max_params.return_value = 1 test_list = self.pk_list[:2] with patch.object(QuerySet, 'count') as mock_method: mock_method.side_effect = (OperationalError(), None) qs = filter_qs_by_pk_list(Delivery.objects.all(), test_list) self.assertEqual(len(qs), 1)
def test_filtering_with_range_convertion_split_range( self, mock_max_params): mock_max_params.return_value = 4 with patch.object(QuerySet, 'count') as mock_method: mock_method.side_effect = (OperationalError(), None) result_qs = filter_qs_by_pk_list(Delivery.objects.all(), self.pk_list) assert set(result_qs.values_list('pk', flat=True)) == set( [5, 6, 7, 9, 10])
def test_filtering_with_range_convertion_single_item( self, mock_max_params): mock_max_params.return_value = 1 with patch.object(QuerySet, 'count') as mock_method: mock_method.side_effect = (OperationalError(), None) result_qs = filter_qs_by_pk_list(Delivery.objects.all(), self.pk_list) assert list(result_qs.values_list( 'pk', flat=True)) == [5] # First item of longest range
def test_filtering_with_range_convertion_inside_range( self, mock_max_params): mock_max_params.return_value = 5 with patch.object(QuerySet, 'count') as mock_method: mock_method.side_effect = (OperationalError(), None) result_qs = filter_qs_by_pk_list(Delivery.objects.all(), self.pk_list) assert len( result_qs ) == 6 # 2 Ranges (4 params, 5 values) + 1 single values assert set([5, 6, 7, 9, 10 ]).issubset(set(result_qs.values_list( 'pk', flat=True))) # First 5 items from 2 ranges
def filter_queryset(self, queryset): """Filter the Given Queryset.""" property_filter_list = [] # Filter by django_filter filters first so we can control the number of sql parameters for name, value in self.form.cleaned_data.items(): if isinstance(self.filters[name], PropertyBaseFilter): property_filter_list.append((name, value)) else: logger.debug(F'Filtering value "{value}" with Filter: "{self.filters[name].__class__.__name__}", ' F'DATA: "{self.filters[name].__dict__}"') queryset = self.filters[name].filter(queryset, value) assert isinstance( # Assert taken from parent function #nosec queryset, models.QuerySet), \ "Expected '%s.%s' to return a QuerySet, but got a %s instead." \ % (type(self).__name__, name, type(queryset).__name__) # Filter By Property Filters if property_filter_list: qs_pk_list = queryset.values_list('pk', flat=True) pk_list = set(qs_pk_list) # Check if we need to preserve the order from the normal Filter filtering preserve_order = None if queryset.ordered: preserve_order = list(qs_pk_list) logger.debug(F'pk_list after normal Filter Filtering {pk_list}') for name, value in property_filter_list: if value not in EMPTY_VALUES: logger.debug(F'Filtering pk_list against value "{value}" with Property Filter: ' F'"{self.filters[name].__class__.__name__}", DATA: "{self.filters[name].__dict__}"') pk_list = self.filters[name].filter_pks(pk_list, queryset, value) logger.debug(F'>>> Resulting pk_list {pk_list}') # If we need to preserve order keep track of the latest order list if self.filters[name].__class__ in PRESERVE_ORDER_FILTERS: preserve_order = pk_list.copy() logger.debug('Filtering Property Filter queryset') queryset = filter_qs_by_pk_list(queryset, pk_list, preserve_order=preserve_order) return queryset
def test_keep_order_with_filtering(self): result_qs = filter_qs_by_pk_list(Delivery.objects.all(), [3, 2, 4], preserve_order=[3, 1, 4, 2]) assert list(result_qs.values_list('pk', flat=True)) == [3, 4, 2]