-
Notifications
You must be signed in to change notification settings - Fork 9
Description
Problem
The current implementation of the full text search introduces new filter classes that extends the Filter class of the django_filters library. Using such filters in a FilterSet class is inconvenient and confusing because they must have specific field names and lookup expressions.
For example, the manual implementation of the trigram filter for a name field looks like the one below because of FloatLookupsInputType is the constant.
input FloatLookupsInputType {
exact: Float
gt: Float
gte: Float
lt: Float
lte: Float
}from graphene_django_filter import AdvancedFilterSet
from graphene_django_filter.filters import TrigramFilter
class ManualFilterSet(AdvancedFilterSet):
name__trigram = TrigramFilter(field_name='name__trigram', lookup_expr='exact')
name__trigram__gt = TrigramFilter(field_name='name__trigram', lookup_expr='gt')
name__trigram__gte = TrigramFilter(field_name='name__trigram', lookup_expr='gte')
name__trigram__lt = TrigramFilter(field_name='name__trigram', lookup_expr='lt')
name__trigram__lte = TrigramFilter(field_name='name__trigram', lookup_expr='lte')This is so confusing and verbose that it is not documented because it is always expected to use filters generation with the fields Meta field. For example.
from graphene_django_filter import AdvancedFilterSet
class AutoFilterSet(AdvancedFilterSet):
class Meta:
fields = {
'name': ('full_text_search',)
}In general, the approach described above works, but it contradicts the logic of building the django_filters library. The 'full_text_search' is not a lookup expression but is used as such expression in the fields dictionary. The name__trigram is not a field name but is used as field name in the TrigramFilter class. The reasons for this approach were to try to reuse code as much as possible and avoid having to implement an additional Advanced DjangoObjectType that extends the DjangoObjectType class.
Suggested solution
The new API should look like this.
from graphene_django_filter import AdvancedFilterSet
class AutoFilterSet(AdvancedFilterSet):
class Meta:
full_text_search = {
'trigram': {
'name': ('exact', 'lt', 'gt',)
},
search_query: ('name', 'email')
search_rank: {
'fields': ('name', 'email')
'lookups': ('exact', 'lt', 'gt',)
}
}The logic of applying filtering and annotations will be moved to the level of the AdvancedFilterSet class, as well as filters of different nature will receive logical settings through a special field of the Meta class. Filters inherited from the Filter class will no longer be explicitly used for filtering with full-text search, so their manual application will no longer be possible.
Caveat
This change requires an implementation of the AdvancedDjangoObjectType class, because the standard DjangoObjectType class will ignore the unknown meta key.
from graphene_django_filter import AdvancedDjangoObjectType
class UserType(AdvancedDjangoObjectType):
class Meta:'
model = User
fields = (
'id',
'name',
'email',
)
filter_fields = {
'name': ('exact',)
}
full_text_search = {
'trigram': {
'name': ('exact', 'lt', 'gt',)
},
search_query: ('name', 'email')
search_rank: {
'fields': ('name', 'email')
'lookups': ('exact', 'lt', 'gt',)
}
}