Coverage for apis_core/apis_entities/filtersets.py: 0%

36 statements  

« prev     ^ index     » next       coverage.py v7.5.3, created at 2025-06-25 10:00 +0000

1import django_filters 

2from django.apps import apps 

3from django.conf import settings 

4from django.db import models 

5from django.forms import DateInput 

6from django.utils.encoding import force_str 

7from simple_history.utils import get_history_manager_for_model 

8 

9from apis_core.generic.filtersets import GenericFilterSet 

10from apis_core.generic.helpers import default_search_fields, generate_search_filter 

11 

12 

13class ModelSearchFilter(django_filters.CharFilter): 

14 """ 

15 This filter is a customized CharFilter that 

16 uses the `generate_search_filter` method to 

17 adapt the search filter to the model that is 

18 searched. 

19 It also extracts sets the help text based on 

20 the fields searched. 

21 """ 

22 

23 def __init__(self, *args, **kwargs): 

24 model = kwargs.pop("model", None) 

25 super().__init__(*args, **kwargs) 

26 

27 if model is not None and "help_text" not in self.extra: 

28 field_names = [field.verbose_name for field in default_search_fields(model)] 

29 # use force_str on the fields verbose names to convert 

30 # lazy instances to string and join the results 

31 fields = ", ".join(map(force_str, field_names)) 

32 self.extra["help_text"] = f"Search in fields: {fields}" 

33 

34 def filter(self, qs, value): 

35 return qs.filter(generate_search_filter(qs.model, value)) 

36 

37 

38def changed_since(queryset, name, value): 

39 history = get_history_manager_for_model(queryset.model) 

40 ids = history.filter(history_date__gt=value).values_list("id", flat=True) 

41 return queryset.filter(pk__in=ids) 

42 

43 

44class AbstractEntityFilterSet(GenericFilterSet): 

45 class Meta(GenericFilterSet.Meta): 

46 filter_overrides = { 

47 models.CharField: { 

48 "filter_class": django_filters.CharFilter, 

49 "extra": lambda f: { 

50 "lookup_expr": "icontains", 

51 }, 

52 }, 

53 } 

54 

55 def __init__(self, *args, **kwargs): 

56 super().__init__(*args, **kwargs) 

57 if model := getattr(self.Meta, "model", False): 

58 self.filters["search"] = ModelSearchFilter(model=model) 

59 self.filters.move_to_end("search", False) 

60 

61 if "apis_core.history" in settings.INSTALLED_APPS: 

62 self.filters["changed_since"] = django_filters.DateFilter( 

63 label="Changed since", 

64 widget=DateInput(attrs={"type": "date"}), 

65 method=changed_since, 

66 ) 

67 

68 if apps.is_installed("apis_core.relations"): 

69 from apis_core.relations.filters import RelationFilter 

70 

71 self.filters["relation"] = RelationFilter()