In my project I use django rest framework. To filter the results I use django_filters backend. There is my code:
models.py
from django.db import models
class Region(models.Model):
name = models.CharField(max_length=100, blank=True, null=False)
class Town(models.Model):
region = models.ForeignKey(Region)
name = models.CharField(max_length=100, blank=True, null=False')
filters.py
import django_filters
from models import Town
class TownFilter(django_filters.FilterSet):
region = django_filters.CharFilter(name="region__name", lookup_type="contains")
town = django_filters.CharFilter(name="name", lookup_type="contains")
class Meta:
model = Town
fields = ['region', 'town']
views.py
from models import Town
from rest_framework import generics
from serializers import TownSerializer
from filters import TownFilter
class TownList(generics.ListAPIView):
queryset = Town.objects.all()
serializer_class = TownSerializer
filter_class = TownFilter
So, I can write ?region=Region_name&town=Town_name to the end of the request url, and the result will be filtered.
But I want to use only one get param in the request url, which can have region or town name as value. For example ?search=Region_name and ?search=Town_name. How can I do this?
Django-filter is a generic, reusable application to alleviate writing some of the more mundane bits of view code. Specifically, it allows users to filter down a queryset based on a model's fields, displaying the form to let them do this. Adding a FilterSet with filterset_class. Using the filterset_fields shortcut.
The DjangoFilterBackend class is used to filter the queryset based on a specified set of fields. This backend class automatically creates a FilterSet (django_filters. rest_framework. FilterSet) class for the given fields. We can also create our own FilterSet class with customized settings.
The root QuerySet provided by the Manager describes all objects in the database table. Usually, though, you'll need to select only a subset of the complete set of objects. The default behavior of REST framework's generic list views is to return the entire queryset for a model manager.
There are a few options, but the easiest way is to just override 'get_queryset' in your API view.
Example from the docs adapted to your use case:
class TownList(generics.ListAPIView):
queryset = Town.objects.all()
serializer_class = TownSerializer
filter_class = TownFilter(generics.ListAPIView)
serializer_class = PurchaseSerializer
def get_queryset(self):
queryset = Town.objects.all()
search_param = self.request.QUERY_PARAMS.get('search', None)
if search_param is not None:
"""
set queryset here or use your TownFilter
"""
return queryset
Another way is to set your search_fields
on the list api view class in combination use the SearchFilter
class. The problem is that if you're filtering over multiple models, you may have to do some additional implementation here to make sure it's looking at exactly what you want. If you're not doing anything fancy, just put double underscores for region for example: region__name
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With