87245

Django Filter Backend

Question:

I'm working with Django rest framework API, I am trying to make a filter by first_name or by last_name or by both of them. This is my <strong>ContactViewSet.py</strong> :

class ContactViewSet(viewsets.ModelViewSet): queryset = Contact.objects.all() serializer_class = ContactSerializer filter_backends = (DjangoFilterBackend, ) filter_fields = ('first_name', 'last_name') lookup_field = 'idContact'

My DRF's settings :

REST_FRAMEWORK = { 'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',), }

My actuel request url looks like :

http://localhost:8000/api/v1/contacts/?first_name=Clair&last_name=Test

But I'm looking for something like this :

http://localhost:8000/api/v1/contacts/?first_name=Cl**&last_name=Tes**

Any help would be appreciated ..

Answer1:

I think the DjangoFilterBackend is mainly equality-based filtering. But you can <a href="https://django-filter.readthedocs.io/en/latest/guide/usage.html#customize-filtering-with-filter-method" rel="nofollow">customize the filtering method</a>.

Also in DRF, for non exact filtering, there is the <a href="http://www.django-rest-framework.org/api-guide/filtering/#searchfilter" rel="nofollow">SearchFilter</a> which makes case-insensitive partial matches searches by default.

Answer2:

What I do, is write custom FilterBackend. Something like this:

# views.py from rest_framework import filters class ObjektFilterBackend(filters.BaseFilterBackend): allowed_fields = ['objekt', 'naziv', 'kategorija', 'zadnja_sprememba'] def filter_queryset(self, request, queryset, view): flt = {} for param in request.query_params: for fld in self.allowed_fields: if param.startswith(fld): flt[param] = request.query_params[param] return queryset.filter(**flt) class ObjektiViewSet(mixins.ListModelMixin, mixins.RetrieveModelMixin, viewsets.GenericViewSet): authentication_classes = ( authentication.TokenAuthentication, authentication.SessionAuthentication) permission_classes = (IsAuthenticated,) queryset = models.Objekt.objects.all() serializer_class = serializers.ObjektSerializer filter_backends = (ObjektFilterBackend, ObjektOrderBackend,) ....

Besides basic filtering (fieldname=value pairs) I can use any <a href="https://docs.djangoproject.com/en/2.0/ref/models/querysets/#field-lookups" rel="nofollow">Django queryset Field Lookups</a> (__gt, __gte, __startswith,...) in my URLs like this:

http://localhost:8000/api/v2/objekti/?naziv__startswith=Apartma&zadnja_sprememba__gte=2018-01-01

And ObjektFilterBackend class could be easily adapted to support searching by pattern.

Just a little warning - this approach is potentially dangerous, because it allows end user to filter also by foreign key field. Something like this also works:

http://localhost:8000/api/v2/objekti/?kategorija__naziv__icontains=sobe

So restrict allowed_fields carefully and not include foreign keys that could lead to related User model.

Answer3:

I solved my problem by modifying my class ContactFilter like this:

<pre class="lang-html prettyprint-override">import django_filters from .models import Contact class ContactFilter(django_filters.FilterSet): class Meta: model = Contact fields = { 'first_name': ['startswith'], 'last_name': ['startswith'], } together = ['first_name', 'last_name']

And in my view I just had to do this :

<pre class="lang-html prettyprint-override">class ContactViewSet(viewsets.ModelViewSet): queryset = Contact.objects.all() serializer_class = ContactSerializer filter_class = ContactFilter

My request url looks like :

<pre class="lang-html prettyprint-override">http://localhost:8000/api/v1/contact/?first_name__contains=Cl&last_name__contains=Tes

But I still wonder if I can have something like this in Django

<pre class="lang-html prettyprint-override">http://localhost:8000/api/v1/contacts/?first_name=Cl**&last_name=Tes**

Answer4:

If your requests aren't too complicated you can also use:

class YourModelViewSet(viewsets.ModelViewSet): queryset = YourModel.objects.all() serializer_class = YourModelSerializer filter_fields = {'some_field': ['startswith']}

Which will enable '?some_field__starswith=text' sintax support in request query params.

I suppose 'startswith' can be replaced with any django standart queryset filter param.

Recommend

  • OperationalError (1054, “Unknown column 'month' in 'field list'”)
  • pywintypes.com error when running pyad.adgroup on flask
  • Python list of list retrieve data
  • Using PATH AMPL solver with Pyomo on Intel Mac OS X
  • Set User Control's default event
  • jQuery ajax security
  • User matching with current data
  • Is there a way to clear some session data from ALL sessions?
  • Search files(key) in s3 bucket takes longer time
  • Azure table query partial partitionkey guid match
  • C Program Compiled with Cygwin and Called from Python Hangs
  • Hide HTML elements without javascript, only CSS
  • Implementing “partial void” in VB
  • custom UITableViewCell with image for highlighting
  • How do I access an unhandled exception in an MVC Error view?
  • How to have background script and something similar to a default popup?
  • Sencha Touch 2.0 Controller refs attribute not working?
  • Typescript - Unable to get 'import' statement to function
  • Google Custom Search with transparent background
  • C++ Partial template specialization - design simplification
  • NHibernate Validation Localization with S#arp Architecture
  • Email format validation in mvc3 view
  • Regex thinks I'm nesting, but I'm not
  • C# - Is there a limit to the size of an httpWebRequest stream?
  • Why HTML5 Canvas with a larger size stretch a drawn line?
  • Spray.io: When (not) to use non-blocking route handling?
  • Bug in WPF DataGrid
  • How to add date and time under each post in guestbook in google app engine
  • Modifying destination and filename of gulp-svg-sprite
  • Redux, normalised entities and lodash merge
  • Why winpcap requires both .lib and .dll to run?
  • Return words with double consecutive letters
  • GridView Sorting works once only
  • Traverse Array and Display in markup
  • Python: how to group similar lists together in a list of lists?
  • NSLayoutConstraint that would pin a view to the bottom edge of a superview
  • coudnt use logback because of log4j
  • how does django model after text[] in postgresql [duplicate]
  • Django query for large number of relationships
  • Busy indicator not showing up in wpf window [duplicate]