Package: drf-query-filter
drf-query-filterdrf-query-filteris used to design fast and complex queries with the 'query' found in the request url.Table of contentsInstallationUsageQuickStartFieldsHow does it work?Installationdrf-query-filter can be installed using pippip3installdrf-query-filterUsageQuickStartInsettings.py:INSTALLED_APPS=[...,'drf_query_filter',...]In views:...fromrest_frameworkimportviewsetsfromdrf_query_filterimportfields,filters...classExampleViewSet(viewsets.GenericViewSet):...filter_backends=[filters.QueryParamFilter,]query_param=[fields.Field('id','id')&fields.Field('user_id','user__id'),fields.RangeDateTimeField('date_created','element__date_created'),]Fieldsthe view needs to define the fields to be used in the query set. there are two ways of doing this.by attribute:query_params=[fields.Field('id')&fields.Field('username','username__icontains'),fields.ConcatField('full_name',['first_name',V(' '),'last_name'])]or by a callable:defget_query_params(self):return[fields.Field('id')&fields.Field('username','username__icontains'),fields.ConcatField('full_name',['first_name',V(' '),'last_name'])]The first value of the Field constructor is the name of the query that it will look for in the request. meaning that in
the case of usingfields.Field('username')it will try to search for the key'username'in the query:http://localhost/path/to/somewhere/?username=valueWith the paramtarget_fieldsof the Field one can tell which are the target fields of the model.Not assigning thetarget_fieldwill assume that the name of the field is the same for the name of the target field.fields.Field('username')# it will user `username` as the target field.To tell whattarget_fieldit is use the paramtarget_fields,
using only a str will target only one field in the model.fields.Field('search','username')Using a list or a tuple will target multiple fields of the model.fields.Field('search',['username','first_name','last_name'])Meaning that the result in the fieldsearch(in this case)will be assigned to all the target fields.How does it work?With the following fields arraigned like this:query_params=[fields.Field('id')&fields.Field('username','user__username__icontains'),fields.RangeDateTimeField('date_created',equal=True)|fields.BooleanField('vip','vip_status'),fields.ConcatField('full_name',['user__first_name',V(' '),'user__last_name'],lookup='icontains'),]Is equivalent to the following lines of code:(if all values are found in the request):queryset=queryset.filter(Q(id='value')&Q(user__username__icontains='value'))queryset=queryset.filter(Q(date_created__gte='value',date_created__lte='value')|Q(vip_status='value'))queryset=queryset\.annotate(first_name_last_name=Concat('user__first_name',V(' '),'user__last_name'))\.filter(Q(first_name_last_name__icontains='value'))If some values are not found in the request, they are ignored, for example:If the request doesn't containfull_nameit will ignore the last field (theannotateandfilter),
And instead it will only do the first two.Request:/?id=9&username=value&date_created=2021-1-1,2021-12-31&vip=truequeryset=queryset.filter(Q(id=9)&Q(user__username__icontains='value'))queryset=queryset.filter(Q(date_created__gte=datetime(year=2021,month=1,day=1),date_created__lte=datetime(year=2021,month=12,day=1))|Q(vip_status=True))Another example where we only ask for theidandfull_name:Request:/?id=10&full_name=Something+Somethingqueryset=queryset.filter(Q(id=10))queryset=queryset\.annotate(first_name_last_name=Concat('user__first_name',V(' '),'user__last_name'))\.filter(Q(first_name_last_name__icontains='Something Something'))