Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor filtersets (inheritance, purpose of classes), restore custom search fields #177

Merged
merged 4 commits into from
Aug 19, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 69 additions & 67 deletions apis_ontology/filtersets.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,29 +103,37 @@ def fuzzy_search_unaccent_trigram(queryset, fields, value):
return trigram_search_filter(queryset, fields, tokens)


class GenericSearchFilterSet(AbstractEntityFilterSet):
class BaseEntityFilterSet(AbstractEntityFilterSet):
"""
Parent class for all entity model classes.
"""

class Meta(AbstractEntityFilterSet.Meta):
filter_overrides = {
**AbstractEntityFilterSet.Meta.filter_overrides,
ArrayField: {
"filter_class": django_filters.MultipleChoiceFilter,
# "extra" attribute not working for fields with choices, see:
# https://github.com/carltongibson/django-filter/issues/1475
"extra": lambda f: {
"lookup_expr": "icontains",
"widget": forms.SelectMultiple,
},
},
}

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if "search" in self.filters:
self.filters.move_to_end("search", False)
if "custom_search" in self.filters:
self.filters.move_to_end("custom_search", False)


class PersonNameMixinFilterSet(GenericSearchFilterSet):
search = django_filters.CharFilter(
field_name=[
"surname",
"forename",
"fallback_name",
"alternative_name",
],
help_text=_("Suche in allen Namensfeldern"),
label=_("Suche: Namen"),
method=fuzzy_search_unaccent_trigram,
)

class TitlesSearch(django_filters.FilterSet):
"""
Search within title and subtitle fields.
"""

class TitlesMixinFilterSet(GenericSearchFilterSet):
search = django_filters.CharFilter(
custom_search = django_filters.CharFilter(
field_name=[
"title",
"subtitle",
Expand All @@ -136,8 +144,16 @@ class TitlesMixinFilterSet(GenericSearchFilterSet):
)


class AlternativeNameMixinFilterSet(GenericSearchFilterSet):
search = django_filters.CharFilter(
class AlternativeNameSearch(django_filters.FilterSet):
"""
Search within name and alternative_name fields.

With the exception of person-like entities (whose names are more complex),
the existence of the latter is assumed to be predicated on the former,
i.e. an entity cannot have an "alternative_name" without a "name".
"""

custom_search = django_filters.CharFilter(
field_name=[
"name",
"alternative_name",
Expand All @@ -148,39 +164,47 @@ class AlternativeNameMixinFilterSet(GenericSearchFilterSet):
)


class PersonFilterSet(PersonNameMixinFilterSet):
class PersonSearch(django_filters.FilterSet):
"""
Search within the various name fields used for persons and person-like
entities (like characters).
"""

custom_search = django_filters.CharFilter(
field_name=[
"surname",
"forename",
"fallback_name",
"alternative_name",
],
help_text=_("Suche in allen Namensfeldern"),
label=_("Suche: Namen"),
method=fuzzy_search_unaccent_trigram,
)


class PersonFilterSet(BaseEntityFilterSet, PersonSearch):
pass


class CharacterFilterSet(PersonNameMixinFilterSet):
class CharacterFilterSet(BaseEntityFilterSet, PersonSearch):
new_fictionality = django_filters.MultipleChoiceFilter(
choices=Character.CharacterFictionality.choices,
lookup_expr="icontains",
)

class Meta(PersonNameMixinFilterSet.Meta):
class Meta(BaseEntityFilterSet.Meta):
fields = {
"new_fictionality": ["icontains"],
}
filter_overrides = {
ArrayField: {
"filter_class": django_filters.MultipleChoiceFilter,
# "extra" attribute not working for fields with choices, see:
# https://github.com/carltongibson/django-filter/issues/1475
"extra": lambda f: {
"lookup_expr": "icontains",
"widget": forms.SelectMultiple,
},
},
}


class VersionCharacterFilterSet(CharacterFilterSet):
pass


class WorkFilterSet(TitlesMixinFilterSet):
search = django_filters.CharFilter(
class WorkFilterSet(BaseEntityFilterSet, TitlesSearch):
custom_search = django_filters.CharFilter(
field_name=[
"title",
"subtitle",
Expand Down Expand Up @@ -237,28 +261,17 @@ class WorkFilterSet(TitlesMixinFilterSet):
lookup_expr="icontains",
)

class Meta(TitlesMixinFilterSet.Meta):
class Meta(BaseEntityFilterSet.Meta):
fields = {
"temporal_order": ["icontains"],
}
filter_overrides = {
ArrayField: {
"filter_class": django_filters.MultipleChoiceFilter,
# "extra" attribute not working for fields with choices, see:
# https://github.com/carltongibson/django-filter/issues/1475
"extra": lambda f: {
"lookup_expr": "icontains",
"widget": forms.SelectMultiple,
},
},
}


class VersionWorkFilterSet(WorkFilterSet):
pass


class ExpressionFilterSet(TitlesMixinFilterSet):
class ExpressionFilterSet(BaseEntityFilterSet, TitlesSearch):
new_edition_type = django_filters.MultipleChoiceFilter(
choices=Expression.EditionTypes.choices,
lookup_expr="icontains",
Expand All @@ -269,45 +282,34 @@ class ExpressionFilterSet(TitlesMixinFilterSet):
lookup_expr="icontains",
)

class Meta(TitlesMixinFilterSet.Meta):
class Meta(BaseEntityFilterSet.Meta):
fields = {
"language": ["icontains"],
}
filter_overrides = {
ArrayField: {
"filter_class": django_filters.MultipleChoiceFilter,
# "extra" attribute not working for fields with choices, see:
# https://github.com/carltongibson/django-filter/issues/1475
"extra": lambda f: {
"lookup_expr": "icontains",
"widget": forms.SelectMultiple,
},
},
}


class VersionExpressionFilterSet(ExpressionFilterSet):
pass


class OrganisationFilterSet(AlternativeNameMixinFilterSet):
class OrganisationFilterSet(BaseEntityFilterSet, AlternativeNameSearch):
pass


class PlaceFilterSet(AlternativeNameMixinFilterSet):
class PlaceFilterSet(BaseEntityFilterSet, AlternativeNameSearch):
pass


class ResearchPerspectiveFilterSet(AlternativeNameMixinFilterSet):
class ResearchPerspectiveFilterSet(BaseEntityFilterSet, AlternativeNameSearch):
pass


class TopicFilterSet(AlternativeNameMixinFilterSet):
class TopicFilterSet(BaseEntityFilterSet, AlternativeNameSearch):
pass


class WorkTypeFilterSet(AlternativeNameMixinFilterSet):
search = django_filters.CharFilter(
class WorkTypeFilterSet(BaseEntityFilterSet, AlternativeNameSearch):
custom_search = django_filters.CharFilter(
field_name=[
"name",
"name_plural",
Expand Down
Loading