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',)
}
}
Problem
The current implementation of the full text search introduces new filter classes that extends the Filter class of the
django_filterslibrary. Using such filters in aFilterSetclass 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
FloatLookupsInputTypeis the constant.This is so confusing and verbose that it is not documented because it is always expected to use filters generation with the
fieldsMeta field. For example.In general, the approach described above works, but it contradicts the logic of building the
django_filterslibrary. The 'full_text_search' is not a lookup expression but is used as such expression in thefieldsdictionary. Thename__trigramis not a field name but is used as field name in theTrigramFilterclass. The reasons for this approach were to try to reuse code as much as possible and avoid having to implement an additionalAdvanced DjangoObjectTypethat extends theDjangoObjectTypeclass.Suggested solution
The new API should look like this.
The logic of applying filtering and annotations will be moved to the level of the
AdvancedFilterSetclass, as well as filters of different nature will receive logical settings through a special field of theMetaclass. Filters inherited from theFilterclass 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
AdvancedDjangoObjectTypeclass, because the standardDjangoObjectTypeclass will ignore the unknown meta key.