예제 #1
0
class PostFilter(FilterSet):
    text = filters.CharFilter(field_name="text", lookup_expr="icontains")
    is_current = filters.BooleanFilter(method='filter_is_current')

    class Meta:
        model = Post
        fields = ['author', 'text', 'pub_date']

    def filter_is_current(self, queryset, name, value):
        set1 = queryset.filter(pub_date__year=2021)
        set2 = queryset.filter(pub_date__month=5)

        return set1 & set2
예제 #2
0
파일: task.py 프로젝트: jerrykan/pulpcore
class TaskFilter(BaseFilterSet):
    state = filters.CharFilter()
    worker = HyperlinkRelatedFilter()
    name = filters.CharFilter()
    started_at = IsoDateTimeFilter(field_name='started_at')
    finished_at = IsoDateTimeFilter(field_name='finished_at')
    parent = HyperlinkRelatedFilter()
    reserved_resources_record = ReservedResourcesFilter()
    created_resources = CreatedResourcesFilter()

    class Meta:
        model = Task
        fields = {
            'state': ['exact', 'in'],
            'worker': ['exact', 'in'],
            'name': ['contains'],
            'started_at': DATETIME_FILTER_OPTIONS,
            'finished_at': DATETIME_FILTER_OPTIONS,
            'parent': ['exact'],
            'reserved_resources_record': ['exact'],
            'created_resources': ['exact']
        }
예제 #3
0
class KadastraalObjectFilter(FilterSet):
    """
    Filter also capable of dealing with landelijk_ids
    """

    verblijfsobject = filters.CharFilter(method="vbo_filter")
    verblijfsobjecten__id = filters.CharFilter(method="vbo_filter")
    verblijfsobjecten__landelijk_id = filters.CharFilter(method="vbo_filter")

    class Meta(object):
        model = models.KadastraalObject

        fields = ('verblijfsobject', 'verblijfsobjecten__id',
                  'verblijfsobjecten__landelijk_id', 'beperkingen__id',
                  'a_percelen__id', 'g_percelen__id')

    def vbo_filter(self, queryset, _filter_name, value):

        if len(value) == 16:
            return queryset.filter(verblijfsobjecten__landelijk_id=value)

        return queryset.filter(verblijfsobjecten__id=value)
예제 #4
0
class MovieFilter(FilterSet):
    # movies/?title=value
    title = filters.CharFilter(method='movie_title_filter')

    class Meta:
        model = Movie
        fields = ['title']

    def movie_title_filter(self, queryset, title, value):
        title = self.request.query_params.get(title, None)
        if title is not None:
            queryset = queryset.filter(title__icontains=value)
        return queryset
예제 #5
0
class DecisionFilter(FilterSet):
    lease = filters.NumberFilter()
    reference_number = filters.CharFilter(lookup_expr="contains")

    class Meta:
        model = Decision
        fields = [
            "lease",
            "reference_number",
            "decision_maker",
            "decision_date",
            "type",
        ]
예제 #6
0
class BouwDossierFilter(FilterSet):
    nummeraanduiding = filters.CharFilter(field_name='adressen__nummeraanduidingen', method='array_contains_filter')
    pand = filters.CharFilter(field_name='adressen__panden', method='array_contains_filter')
    verblijfsobject = filters.CharFilter(field_name='adressen__verblijfsobjecten', method='array_contains_filter')
    openbareruimte = filters.CharFilter(field_name='adressen__openbareruimte_id')
    min_datering = filters.CharFilter(field_name='datering__year', lookup_expr='gte')
    max_datering = filters.CharFilter(field_name='datering__year', lookup_expr='lte')
    subdossier = filters.CharFilter(field_name='documenten__subdossier_titel', lookup_expr='istartswith')
    dossiernr = filters.NumberFilter()
    dossier = filters.CharFilter(method='dossier_with_stadsdeel')
    stadsdeel = filters.CharFilter()
    dossier_type = filters.CharFilter()

    class Meta:
        model = models.BouwDossier

        fields = (
            'dossiernr',
            'stadsdeel',
            'nummeraanduiding',
            'verblijfsobject',
            'pand',
            'openbareruimte',
            'min_datering',
            'max_datering',
            'subdossier',
            'olo_liaan_nummer',
        )

    def dossier_with_stadsdeel(self, queryset, _filter_name, value):
        stadsdeel, dossiernr = tools.separate_dossier(value)
        return queryset.filter(stadsdeel=stadsdeel, dossiernr=dossiernr)

    def array_contains_filter(self, queryset, _filter_name, value):
        if not isinstance(value, list):
            value = [value]
        lookup = '%s__%s' % (_filter_name, 'contains')
        return queryset.filter(**{lookup: value}).distinct()
예제 #7
0
파일: filters.py 프로젝트: spreeker/signals
class LocationFilter(FilterSet):
    """
    """
    id = filters.CharFilter()
    in_bbox = filters.CharFilter(method='in_bbox_filter', label='bbox')
    location = filters.CharFilter(method="locatie_filter", label='x,y,r')

    stadsdeel = filters.ChoiceFilter(choices=STADSDELEN)
    buurt_code = filters.ChoiceFilter(choices=buurt_choices)

    class Meta(object):
        model = Location
        fields = (
            "id",
            "_signal__id",
            "buurt_code",
            "signal__location__stadsdeel",
            "signal__location__buurt_code",
            "created_at",
            "in_bbox",
            "location",
        )

    def locatie_filter(self, qs, name, value):
        lon, lat, radius = parse_xyr(value)
        point = Point(lon, lat)

        return qs.filter(geometrie__dwithin=(point,
                                             bbox.dist_to_deg(radius, lat)))

    def in_bbox_filter(self, qs, name, value):
        bbox_values, err = bbox.valid_bbox(value)
        lon1, lat1, lon2, lat2 = bbox_values
        poly_bbox = Polygon.from_bbox((lon1, lat1, lon2, lat2))

        if err:
            raise ValidationError(f"bbox invalid {err}:{bbox_values}")
        return qs.filter(geometrie__bboverlaps=poly_bbox)
예제 #8
0
class DateFilter(FilterSet):
    vanaf = filters.CharFilter(label='vanaf', method='vanaf_filter')
    tot = filters.CharFilter(label='tot', method='tot_filter')
    op = filters.CharFilter(label='op', method='op_filter')

    class Meta:
        model = models.Drukteindex
        fields = ['timestamp', 'vanaf', 'tot', 'op', 'vollcode']

    def vanaf_filter(self, queryset, _name, value):
        date = convert_to_date(value)
        if not date:
            raise ValidationError(
                'Please insert a datetime Year-Month-Day-Hour-Minute-Second, like: 26-10-2017-16-00-00'
            )
        queryset = queryset.filter(timestamp__gte=date)

        return queryset

    def tot_filter(self, queryset, _name, value):
        date = convert_to_date(value)
        if not date:
            raise ValidationError(
                'Please insert a datetime Year-Month-Day-Hour-Minute-Second, like: 26-10-2017-16-00-00'
            )
        queryset = queryset.filter(timestamp__lte=date)

        return queryset

    def op_filter(self, queryset, _name, value):
        date = convert_to_date(value)
        if not date:
            raise ValidationError(
                'Please insert a datetime Year-Month-Day-Hour-Minute-Second, like: 26-10-2017-16-00-00'
            )
        queryset = queryset.filter(timestamp=date)

        return queryset
예제 #9
0
class ReviewFilter(FilterSet):
    # reviews/?comment=value
    comment = filters.CharFilter(method='comments_filter')

    class Meta:
        model = Review
        fields = ['comment']

    # 'value'가 들어간 comment 필터링
    def comments_filter(self, queryset, comment, value):
        comment = self.request.query_params.get(comment, None)
        if comment is not None:
            queryset = queryset.filter(comment__icontains=value)
        return queryset
예제 #10
0
class JurisdictionFilter(FilterSet):
    whitelisted = filters.BooleanFilter()
    slug = filters.ChoiceFilter(choices=jur_choices, label='Name')
    name_long = filters.CharFilter(label='Long Name')

    class Meta:
        model = models.Jurisdiction
        fields = [
            'id',
            'name',
            'name_long',
            'whitelisted',
            'slug',
        ]
예제 #11
0
class SubjectFilter(FilterSet):
    """
    Filter subjecten.
    """
    buurt = filters.CharFilter(method="buurt_filter", label='buurt')

    zakelijk_recht = filters.NumberFilter(method="recht_filter", label='recht')

    bewoners = filters.BooleanFilter(method="bewoners_filter")

    class Meta(object):
        model = models.KadastraalSubject

        fields = (
            'naam',
            'type',
            'buurt',
            'kvknummer',
            'statutaire_naam',
            'zakelijk_recht',
        )

    def buurt_filter(self, queryset, _filter_name, value):
        """
        Buurt code 4 chars
        """
        recht_type = 2  # eigenaar

        if 'zakelijk_recht' in self.request.GET:
            recht_type = self.request.GET['zakelijk_recht']

        if len(value) != 4:
            raise drf_serializers.ValidationError('Buurt vollcode is 4 chars')

        # remove ordering.
        # SUPER SLOW because of some weirdness.
        qs = queryset.order_by()

        return qs.filter(rechten__verblijfsobjecten__buurt__vollcode=value,
                         rechten__aard_zakelijk_recht__code=recht_type)

    def recht_filter(self, queryset, _filter_name, value):

        if self.request.GET['buurt']:
            # will be recht filter will be done
            # in buurt filter
            return queryset

        return queryset.filter(rechten__aard_zakelijk_recht__code=value)
예제 #12
0
class SidconFilter(FilterSet):
    """Filtering on sidcon fill level entries."""

    container_id = filters.CharFilter(method='container_filter',
                                      label='container id')

    site_id = filters.CharFilter(method='site_filter', label='short site id')

    days_back = filters.NumberFilter(method='delta_day_filter',
                                     label='days back')

    class Meta(object):
        model = SidconFillLevel

        fields = {
            "scraped_at": FILTERS,
            "filling": FILTERS,
            "communication_date_time": FILTERS,
            "container_id": ['exact'],
            "days_back": ['exact'],
            "valid": ['exact'],
            "short_id": ['exact'],
            "site_id": ['exact'],
        }

    def container_filter(self, qs, name, value):
        return qs.filter(description=value)

    def site_filter(self, qs, name, value):
        return qs.filter(site_id=value)

    def delta_day_filter(self, qs, name, value):
        today = datetime.datetime.now()
        delta = datetime.timedelta(days=int(value))
        filter_day = today - delta
        return qs.filter(communication_date_time__gt=filter_day)
예제 #13
0
class DistributionFilter(BaseFilterSet):
    # e.g.
    # /?name=foo
    # /?name__in=foo,bar
    # /?base_path__contains=foo
    # /?base_path__icontains=foo
    name = filters.CharFilter()
    base_path = filters.CharFilter()
    pulp_label_select = LabelSelectFilter()

    def __init__(self, *args, **kwargs):
        """Initialize a DistributionFilter and emit deprecation warnings"""
        deprecation_logger.warn(
            _("DistributionFilter is deprecated and could be removed as early as "
              "pulpcore==3.13; use pulpcore.plugin.serializers.NewDistributionFilter instead."
              ))
        return super().__init__(*args, **kwargs)

    class Meta:
        model = BaseDistribution
        fields = {
            "name": NAME_FILTER_OPTIONS,
            "base_path": ["exact", "contains", "icontains", "in"],
        }
예제 #14
0
class Pulp2RepositoriesFilter(BaseFilterSet):
    """
    Filter for Pulp2Repositories ViewSet.
    """
    pulp2_repo_id = filters.CharFilter()
    is_migrated = filters.BooleanFilter()
    not_in_plan = filters.BooleanFilter()

    class Meta:
        model = Pulp2Repository
        fields = {
            'pulp2_repo_id': ['exact', 'in'],
            'is_migrated': ['exact'],
            'not_in_plan': ['exact']
        }
예제 #15
0
def filter_factory(ds_name, model):
    model_name = ds_name.upper() + 'GenericFilter'
    ds = DataSet.objects.get(name=ds_name)
    name_field = ds.name_field or 'UNKNOWN'
    geometry_field = ds.geometry_field or 'UNKNOWN'
    geometry_type = ds.geometry_type or 'UNKNOWN'
    fields = [name_field, geometry_field]
    location_filter_name = ':'.join([geometry_field, geometry_type])
    location = filters.CharFilter(field_name=location_filter_name,
                                  method="location_filter")
    name = filters.CharFilter(field_name=name_field, method="name_filter")

    new_meta_attrs = {
        'model': model,
        'fields': fields,
    }
    new_meta = type('Meta', (object, ), new_meta_attrs)
    new_attrs = {
        '__module__': 'various_small_datasets.gen_api.filters',
        'Meta': new_meta,
        geometry_field: location,
        name_field: name,
    }
    return type(model_name, (GenericFilter, ), new_attrs)
class UserFilter(FilterSet):
    nickname = filters.CharFilter(field_name='nickname',
                                  lookup_expr="icontains")
    is_hy1 = filters.BooleanFilter(method='filter_is_hy1')

    class Meta:
        model = User
        fields = ['nickname']

    def filter_is_hy1(self, queryset, name, value):
        filtered_queryset = queryset.filter(nickname__contains="1")
        filtered_queryset2 = queryset.filter(~Q(nickname__contains="1"))
        if value == True:
            return filtered_queryset
        else:
            return filtered_queryset2
예제 #17
0
class Pulp2RepositoriesFilter(BaseFilterSet):
    """
    Filter for Pulp2Repositories ViewSet.
    """

    pulp2_repo_id = filters.CharFilter()
    is_migrated = filters.BooleanFilter()
    not_in_plan = filters.BooleanFilter()

    class Meta:
        model = Pulp2Repository
        fields = {
            "pulp2_repo_id": ["exact", "in"],
            "is_migrated": ["exact"],
            "not_in_plan": ["exact"],
        }
예제 #18
0
class RemoteFilter(BaseFilterSet):
    """
    Plugin remote filter should:
     - inherit from this class
     - add any specific filters if needed
     - define a `Meta` class which should:
       - specify a plugin remote model for which filter is defined
       - extend `fields` with specific ones
    """

    name = filters.CharFilter()
    pulp_last_updated = IsoDateTimeFilter()

    class Meta:
        model = Remote
        fields = {"name": NAME_FILTER_OPTIONS, "pulp_last_updated": DATETIME_FILTER_OPTIONS}
예제 #19
0
class FileSystemExporterFilter(BaseFilterSet):
    """
    Plugin file system exporter filter should:
     - inherit from this class
     - add any specific filters if needed
     - define a `Meta` class which should:
       - specify a plugin remote model for which filter is defined
       - extend `fields` with specific ones
    """
    name = filters.CharFilter()

    class Meta:
        model = FileSystemExporter
        fields = {
            'name': NAME_FILTER_OPTIONS,
        }
예제 #20
0
class ParkeervakFilter(FilterSet):
    id = filters.CharFilter()

    class Meta(object):
        model = Parkeervak
        fields = (
            'id',
            'buurtcode',
            'stadsdeel',
            'straatnaam',
            'soort',
            'aantal',
            'type',
            'e_type',
            'bord',
        )
예제 #21
0
class TaskFilter(filterset.FilterSet):
    state = filters.CharFilter()
    worker = HyperlinkRelatedFilter()
    started_at = filters.IsoDateTimeFilter(name='started_at')
    finished_at = filters.IsoDateTimeFilter(name='finished_at')
    parent = HyperlinkRelatedFilter()

    class Meta:
        model = Task
        fields = {
            'state': ['exact', 'in'],
            'worker': ['exact', 'in'],
            'started_at': DATETIME_FILTER_OPTIONS,
            'finished_at': DATETIME_FILTER_OPTIONS,
            'parent': ['exact']
        }
예제 #22
0
class GenericFilter(FilterSet):
    format = filters.CharFilter(method="format_filter")

    class Meta(object):
        model = None
        fields = ()

    @staticmethod
    def location_filter(queryset, _filter_name, value):
        """
        Filter based on the geolocation. This filter actually
        expect 2 or 3 numerical values: x, y and optional radius
        The value given is broken up by ',' and converted
        to the value tuple
        """

        point, radius, err = validate_x_y(value)

        if err:
            log.exception(err)
            raise rest_serializers.ValidationError(err)

        # Creating one big queryset
        (geo_field, geo_type) = _filter_name.split(':')

        if geo_type.lower() == 'polygon' and radius is None:
            args = {'__'.join([geo_field, 'contains']): point}
            biz_results = queryset.filter(**args)
        elif radius is not None:
            args = {'__'.join([geo_field, 'dwithin']): (point, D(m=radius))}
            biz_results = queryset.filter(**args).annotate(
                afstand=Distance(geo_field, point))
        else:
            err = "Radius in argument expected"
            log.exception(err)
            raise rest_serializers.ValidationError(err)
        return biz_results

    @staticmethod
    def name_filter(queryset, _filter_name, value):
        args = {'__'.join([_filter_name, 'icontains']): value}
        return queryset.filter(**args)

    @staticmethod
    def format_filter(queryset, _filter_name, value):
        return queryset
예제 #23
0
class ExporterFilter(BaseFilterSet):
    """
    Plugin exporter filter should:
     - inherit from this class
     - add any specific filters if needed
     - define a `Meta` class which should:
       - specify a plugin exporter model for which filter is defined
       - extend `fields` with specific ones
    """
    name = filters.CharFilter()
    last_export = IsoDateTimeFilter()

    class Meta:
        model = Exporter
        fields = {
            'name': NAME_FILTER_OPTIONS,
            'last_export': DATETIME_FILTER_OPTIONS
        }
예제 #24
0
파일: filters.py 프로젝트: spreeker/signals
class UserFilterSet(FilterSet):
    id = filters.NumberFilter()
    username = filters.CharFilter(lookup_expr='icontains')
    active = filters.BooleanFilter(field_name='is_active')

    role = filters.ModelMultipleChoiceFilter(queryset=_get_group_queryset(),
                                             to_field_name='name',
                                             field_name='groups__name')

    order = OrderingExtraKwargsFilter(
        fields=(
            ('username', 'username'),
            ('is_active', 'active'),
        ),
        extra_kwargs={
            'username': {'apply': Lower}  # Will apply the Lower function when ordering
        }
    )
예제 #25
0
class MetingenFilter(FilterSet):
    """
    Filter metingen op bbox
    """

    bbox = filters.CharFilter(method="bbox_filter")

    class Meta(object):
        model = models.Scan

        fields = (
            'bbox',
            'scan_moment',
            'device_id',
            'scan_source',
            'nha_hoogte',
            'nha_nr',
            'qualcode',
            'buurtcode',
            'sperscode',
            'parkeervak_id',
            'parkeervak_soort',
            'bgt_wegdeel',
            'bgt_wegdeel_functie',
        )

    def box_filter(self, queryset, _filter_name, value):

        bbox_values, err = bbox.valid_bbox(value)

        if err:
            return queryset

        lat1, lon1, lat2, lon2 = bbox_values
        poly_bbox = Polygon.from_bbox((lon1, lat1, lon2, lat2))

        return queryset.filter(
            Q(**{"geometrie__bboverlaps": poly_bbox}))
예제 #26
0
class SpaceFilter(rest_framework.FilterSet):
    contains_more_than_n_categories = rest_framework.CharFilter(
        label=('Содержится видов животных больше чем n:'),
        method="filter_by_categories_count")
    categories__animals__name = filters.CharFilter(
        label=('Фильтр по имени животного:'))
    categories__animals__description = filters.CharFilter(
        label=('Фильтр по описанию животного:'))
    categories__animals__gender = filters.CharFilter(
        label=('Фильтр по полу животного:'))
    categories__animals__age = filters.CharFilter(
        label=('Фильтр по возрасту животного:'))
    categories__animals__created_at = filters.CharFilter(
        label=('Фильтр по дате появления животного:'))
    categories__animals__color = filters.CharFilter(
        label=('Фильтр по цвету животного:'))

    class Meta:
        model = Space
        fields = [
            "name",
            "placementperiods",
            "description",
            "illumination",
            "type",
            "square",
            "categories__animals__name",
            "categories__animals__description",
            "categories__animals__gender",
            "categories__animals__age",
            "categories__animals__created_at",
            "categories__animals__color",
        ]

    def filter_by_categories_count(self, queryset, name, value):
        queryset = Space.objects.annotate(
            num_categories=Count('categories')).filter(
                num_categories__gt=value)
        return queryset
예제 #27
0
class AnimalFilter(rest_framework.FilterSet):
    category__space__name = filters.CharFilter(
        label=('Фильтр по имени вольера:'))
    category__space__created_at = filters.CharFilter(
        label=('Фильтр по дате создания вольера:'))
    category__space__description = filters.CharFilter(
        label=('Фильтр по описанию вольера:'))
    category__space__type = filters.CharFilter(
        label=('Фильтр по типу вольера:'))
    category__space__square = filters.CharFilter(
        label=('Фильтр по площади вольера:'))
    category__space__illumination = filters.CharFilter(
        label=('Фильтр по типу освещения в вольере:'))

    class Meta:
        model = Animal
        fields = [
            "category__space__name",
            "category__space__created_at",
            "category__space__description",
            "category__space__type",
            "category__space__square",
            "category__space__illumination",
        ]
예제 #28
0
class OrderOptionFilter(FilterSet):
    customer_code = filters.CharFilter(help_text='客户代码')
예제 #29
0
class FreightTMOrdFilterSet(FilterSet):
    channel_code = filters.CharFilter(help_text='客户代码')
    freight = filters.NumberFilter(help_text='运单')
예제 #30
0
class SignalFilterSet(FilterSet):
    id = filters.NumberFilter()
    address_text = filters.CharFilter(field_name='location__address_text', lookup_expr='icontains')
    area_code = filters.ChoiceFilter(field_name='location__area_code', choices=area_choices)
    area_type_code = filters.ChoiceFilter(field_name='location__area_type_code', choices=area_type_choices)
    buurt_code = filters.MultipleChoiceFilter(field_name='location__buurt_code', choices=buurt_choices)
    category_id = filters.MultipleChoiceFilter(field_name='category_assignment__category_id',
                                               choices=category_choices)
    category_slug = filters.ModelMultipleChoiceFilter(
        queryset=_get_child_category_queryset(),
        to_field_name='slug',
        field_name='category_assignment__category__slug',
    )
    contact_details = filters.MultipleChoiceFilter(method='contact_details_filter', choices=contact_details_choices)
    created_before = filters.IsoDateTimeFilter(field_name='created_at', lookup_expr='lte')
    directing_department = filters.MultipleChoiceFilter(
        method='directing_department_filter',
        choices=department_choices
    )
    created_after = filters.IsoDateTimeFilter(field_name='created_at', lookup_expr='gte')
    feedback = filters.ChoiceFilter(method='feedback_filter', choices=feedback_choices)
    has_changed_children = filters.MultipleChoiceFilter(method='has_changed_children_filter', choices=boolean_choices)
    kind = filters.MultipleChoiceFilter(method='kind_filter', choices=kind_choices)  # SIG-2636
    incident_date = filters.DateFilter(field_name='incident_date_start', lookup_expr='date')
    incident_date_before = filters.DateFilter(field_name='incident_date_start', lookup_expr='date__gte')
    incident_date_after = filters.DateFilter(field_name='incident_date_start', lookup_expr='date__lte')
    maincategory_slug = filters.ModelMultipleChoiceFilter(
        queryset=_get_parent_category_queryset(),
        to_field_name='slug',
        field_name='category_assignment__category__parent__slug',
    )
    note_keyword = filters.CharFilter(method='note_keyword_filter')
    priority = filters.MultipleChoiceFilter(field_name='priority__priority', choices=Priority.PRIORITY_CHOICES)
    source = filters.MultipleChoiceFilter(choices=source_choices)
    stadsdeel = filters.MultipleChoiceFilter(field_name='location__stadsdeel', choices=stadsdelen_choices)
    status = filters.MultipleChoiceFilter(field_name='status__state', choices=status_choices)
    type = filters.MultipleChoiceFilter(field_name='type_assignment__name', choices=Type.CHOICES)
    updated_before = filters.IsoDateTimeFilter(field_name='updated_at', lookup_expr='lte')
    updated_after = filters.IsoDateTimeFilter(field_name='updated_at', lookup_expr='gte')

    def _cleanup_form_data(self):
        """
        Cleanup the form data
        """
        self.form.cleaned_data.pop('category_slug', None)
        self.form.cleaned_data.pop('maincategory_slug', None)

        if not self.form.cleaned_data.get('area_code', None) or not self.form.cleaned_data.get('area_type_code', None):
            self.form.cleaned_data.pop('area_code', None)
            self.form.cleaned_data.pop('area_type_code', None)

    def filter_queryset(self, queryset):
        """
        Add custom category filtering to the filter_queryset
        """
        if not self.form.cleaned_data['category_id']:
            main_categories = self.form.cleaned_data['maincategory_slug']
            sub_categories = self.form.cleaned_data['category_slug']

            if main_categories or sub_categories:
                queryset = queryset.filter(
                    Q(category_assignment__category__parent_id__in=[c.pk for c in main_categories]) |
                    Q(category_assignment__category_id__in=[c.pk for c in sub_categories])
                )

        self._cleanup_form_data()
        queryset = super(SignalFilterSet, self).filter_queryset(queryset=queryset)
        return queryset.distinct()

    # Custom filter functions

    def contact_details_filter(self, queryset, name, value):
        """
        Filter `signals.Signal` instances according to presence of contact details.
        """
        choices = value  # we have a MultipleChoiceFilter ...

        # Deal with all choices selected, or none selected:
        if len(choices) == len(contact_details_choices()):
            # No filters are present, or ... all filters are present. In that
            # case we want all Signal instances with an email address, or a
            # phone number, or none of those (according to) the UX design.
            # This is the same as not filtering, hence in both cases just
            # return the queryset.
            return queryset

        # Set-up our Q objects for the individual options.
        has_no_email = (Q(reporter__email__isnull=True) | Q(reporter__email=''))
        has_no_phone = (Q(reporter__phone__isnull=True) | Q(reporter__phone=''))
        is_anonymous = has_no_email & has_no_phone

        q_objects = {
            'email': ~has_no_email,
            'phone': ~has_no_phone,
            'none': is_anonymous,
        }

        # The individual choices have to be combined using logical OR:
        q_total = q_objects[choices.pop()]
        while choices:
            q_total |= q_objects[choices.pop()]

        return queryset.filter(q_total)

    def directing_department_filter(self, queryset, name, value):
        """
        Filter Signals on directing department.

        * A directing department can only be set on a Parent Signal
        * When providing the option "null" select all parent Signals without one or more directing departments
        * When providing on or more department codes as options select all parent Signals which match directing
          departments

        Example 1: "?directing_department=ASC" will select all parent Signals where ASC is the directing department
        Example 2: "?directing_department=ASC&directing_department=null" will select all parent Signals without a
                   directing department OR ASC as the directing department
        Example 3: "?directing_department=null" will select all parent Signals without a directing department
        """
        choices = value  # we have a MultipleChoiceFilter ...
        if len(choices) == len(department_choices()):
            # No filters are present, or ... all filters are present. In that case we want all Signal instances
            return queryset

        # Directing departments are only set on parent Signals
        parent_q_filter = (Q(parent__isnull=True) & Q(children__isnull=False))

        if 'null' in choices and len(choices) == 1:
            # "?directing_department=null" will select all parent Signals without a directing department
            return queryset.filter(
                parent_q_filter &
                (
                    Q(directing_departments_assignment__isnull=True) |
                    Q(directing_departments_assignment__departments__isnull=True)
                )
            )
        elif 'null' in choices and len(choices) > 1:
            # "?directing_department=ASC&directing_department=null" will select all parent Signals without a directing
            # department OR ASC as the directing department
            choices.pop(choices.index('null'))
            return queryset.filter(
                parent_q_filter & (
                    Q(directing_departments_assignment__isnull=True) |
                    Q(directing_departments_assignment__departments__isnull=True) |
                    Q(directing_departments_assignment__departments__code__in=choices)
                )
            )
        elif len(choices):
            # "?directing_department=ASC" will select all parent Signals where ASC is the directing department
            return queryset.filter(
                parent_q_filter &
                Q(directing_departments_assignment__departments__code__in=choices)
            )
        return queryset

    def feedback_filter(self, queryset, name, value):
        # Only signals that have feedback
        queryset = queryset.annotate(feedback_count=Count('feedback')).filter(feedback_count__gte=1)

        if value in ['satisfied', 'not_satisfied']:
            is_satisfied = True if value == 'satisfied' else False
            queryset = queryset.annotate(
                feedback_max_created_at=Max('feedback__created_at'),
                feedback_max_submitted_at=Max('feedback__submitted_at')
            ).filter(
                feedback__is_satisfied=is_satisfied,
                feedback__submitted_at__isnull=False,
                feedback__created_at=F('feedback_max_created_at'),
                feedback__submitted_at=F('feedback_max_submitted_at')
            )
        elif value == 'not_received':
            queryset = queryset.annotate(
                feedback_max_created_at=Max('feedback__created_at')
            ).filter(
                feedback__submitted_at__isnull=True,
                feedback__created_at=F('feedback_max_created_at')
            )

        return queryset

    def kind_filter(self, queryset, name, value):
        choices = value  # we have a MultipleChoiceFilter ...

        if (len(choices) == len(kind_choices())
                or {'signal', 'parent_signal', 'child_signal'} == set(choices)
                or {'parent_signal', 'exclude_parent_signal'} == set(choices)):
            return queryset

        q_objects = {
            'signal': (Q(parent__isnull=True) & Q(children__isnull=True)),
            'parent_signal': (Q(parent__isnull=True) & Q(children__isnull=False)),
            'exclude_parent_signal': ~(Q(parent__isnull=True) & Q(children__isnull=False)),
            'child_signal': (Q(parent__isnull=False)),
        }

        q_filter = q_objects[choices.pop()]
        while choices:
            q_filter |= q_objects[choices.pop()]

        return queryset.filter(q_filter) if q_filter else queryset

    def note_keyword_filter(self, queryset, name, value):
        return queryset.filter(notes__text__icontains=value)

    def has_changed_children_filter(self, queryset, name, value):
        # we have a MultipleChoiceFilter ...
        choices = list(set(map(lambda x: True if x in [True, 'True', 'true', 1] else False, value)))
        q_filter = Q(children__isnull=False)
        if len(choices) == 2:
            return queryset.filter(q_filter)

        if True in choices:
            q_filter &= Q(updated_at__lt=F('children__updated_at'))  # noqa Selects all parent signals with changes in the child signals

        if False in choices:
            q_filter &= Q(updated_at__gt=F('children__updated_at'))  # noqa Selects all parent signals with NO changes in the child signals

        return queryset.filter(q_filter)