Package: django-filter-autotools
django-filter-autotoolsInstallationEither using pippython-mpipinstalldjango-filter-autotoolsor directly copying the filedjango_filters_autotools/mixins.pyinto your project.DefaultLookupsMixinBy default django-filter FilterSet class will only generateexactlookups if given a list of fields. This mixin can be used to customize this behaviour:classMyFilterSet(DefaultLookupsMixin,FilterSet):DEFAULT_LOOKUPS={models.CharField:['exact','icontains'],models.IntegerField:['exact','lt','lte','gt','gte','range']}MyFilterSetwill automatically generate filters for all these lookups for any field included infieldsiffieldsis an array. In the case thatfieldsis a dictionary, defaults will be generated for any key havingNoneas value.PseudoLookupsMixinWe can use this mixin to patch the FilterSet filter creation algorithm to understand some lookups which are not registered into Django. Two common scenarios are checking whether a string is empty, adding "exclusion" filters (not) and adding "conjoined" filters (and for m2m):classEmptyStringFilter(filters.BooleanFilter):deffilter(self,qs,value):ifvalueinEMPTY_VALUES:returnqsexclude=self.exclude^(valueisFalse)method=qs.excludeifexcludeelseqs.filterreturnmethod(**{self.field_name:""})classMyFilterSet(PseudoLookupsMixin,FilterSet):PSEUDO_LOOKUPS={'isempty':{'behaves_like':'isnull','filter_class':EmptyStringFilter,},'not_icontains':{'behaves_like':'icontains','filter_class':None,'replace_with':'icontains','extra':lambdaf:{'exclude':True}},'exact_all':{'behaves_like':'exact','filter_class':None,'replace_with':'exact','extra':lambdaf:{'conjoined':True}}}Under the hood this works by replacing the lookup with the one specified in thebehaves_likekey, running the filter creation algorithm and then patching the filters if necessary. This way any transformer or any extra lookups registered into Django will also be available.PSEUDO_LOOKUPSis a dictionary whose keys are the new lookups to be supported and the values are dictionary with the following keys:behaves_like: should be a lookup registered in Django with similar semantics.filter_class: filter class to be used for this lookup. If not specified or set to None, the one chosen django-filter for thebehaves_likelookup will be used. Note that these may be fine-tuned by overriding theFILTER_FOR_DBFIELD_DEFAULTSdictionary.replace_with: if present the filter class is patched so that its__init__method replaces the new lookup with this value.extra: if present the object returned from applying this function to the field will be merged into the filter class kwargs.Override thefilter_for_pseudolookupclass method on the FilterSet if you need to choose different filter classes depending on both the field type and the lookup.Integrating everything into DRF by defaultComplete example making available several lookups by default for all fields of typeCharField, and conjoined filters for all fields of typeManyToManyField:filters.py:fromdjango_filtersimportrest_frameworkasfiltersfromdjango.dbimportmodelsfromdjango.core.validatorsimportEMPTY_VALUESfromdjango_filters_autotools.mixinsimport*classEmptyStringFilter(filters.BooleanFilter):deffilter(self,qs,value):ifvalueinEMPTY_VALUES:returnqsexclude=self.exclude^(valueisFalse)method=qs.excludeifexcludeelseqs.filterreturnmethod(**{self.field_name:""})classMyFilterSet(DefaultLookupsMixin,PseudoLookupsMixin,filters.FilterSet):PSEUDO_LOOKUPS={'isempty':{'behaves_like':'isnull','filter_class':EmptyStringFilter,},'not_icontains':{'behaves_like':'icontains','filter_class':None,'replace_with':'icontains','extra':lambdaf:{'exclude':True}},'exact_all':{'behaves_like':'exact','filter_class':None,'replace_with':'exact','extra':lambdaf:{'conjoined':True}}}DEFAULT_LOOKUPS={models.CharField:['exact','icontains','isempty','not_icontains'],models.ManyToManyField:['exact','exact_all'],}classMyFilterBackend(filters.DjangoFilterBackend):filterset_base=MyFilterSetsettings.py:REST_FRAMEWORK={'DEFAULT_FILTER_BACKENDS':['path.to.filters.MyFilterBackend',],}More infoPyPI projectGithub page