Django REST framework - filtering against query param

前端 未结 3 611
甜味超标
甜味超标 2020-12-23 00:17

So I created my \"API\" using REST framework, now trying to do filtering for it. That\'s how my models.py look like more or less:

class Airline(         


        
相关标签:
3条回答
  • 2020-12-23 00:25

    So with the @limelights I managed to do what I wanted, here is the code:

    class PassengerList(generics.ListCreateAPIView):
        model = Passenger
        serializer_class = PassengerSerializer
    
        # Show all of the PASSENGERS in particular WORKSPACE
        # or all of the PASSENGERS in particular AIRLINE
        def get_queryset(self):
            queryset = Passenger.objects.all()
            workspace = self.request.query_params.get('workspace')
            airline = self.request.query_params.get('airline')
    
            if workspace:
                queryset = queryset.filter(workspace_id=workspace)
            elif airline:
                queryset = queryset.filter(workspace__airline_id=airline)
    
            return queryset
    
    0 讨论(0)
  • 2020-12-23 00:31

    You can get the same functionality out of the box just by using django-filter package as stated in the docs http://www.django-rest-framework.org/api-guide/filtering/#djangofilterbackend

    from rest_framework import filters 
    
    class PassengerList(generics.ListCreateAPIView):
        model = Passenger
        serializer_class = PassengerSerializer
        queryset = Passenger.objects.all()
        filter_backends = (filters.DjangoFilterBackend,)
        filter_fields = ('workspace', 'workspace__airline')
    

    In this case you will have to make filtering using 'workspace=1' or 'workspace__airline=1'

    0 讨论(0)
  • 2020-12-23 00:34

    This django app applies filters on the queryset of a view using the incoming query parameters in an clean and elegant way.

    Which can be installed with pip as pip install drf-url-filters

    Usage Example

    validations.py

    from filters.schema import base_query_param_schema
    from filters.validations import (
        CSVofIntegers,
        IntegerLike,
        DatetimeWithTZ
    )
    
    # make a validation schema for players filter query params
    players_query_schema = base_query_param_schema.extend(
        {
            "id": IntegerLike(),
            "name": unicode,
            "team_id": CSVofIntegers(),  # /?team_id=1,2,3
            "install_ts": DatetimeWithTZ(),
            "update_ts": DatetimeWithTZ(),
        }
    )
    

    views.py

    from rest_framework import (
        viewsets,
        filters,
    )
    
    from .models import Player, Team
    from .serializers import PlayerSerializer, TeamSerializer
    from .pagination import ResultSetPagination
    from .validations import teams_query_schema, players_query_schema
    from filters.mixins import (
        FiltersMixin,
    )
    
    
    class PlayersViewSet(FiltersMixin, viewsets.ModelViewSet):
        """
        This viewset automatically provides `list`, `create`, `retrieve`,
        `update` and `destroy` actions.
        """
        serializer_class = PlayerSerializer
        pagination_class = ResultSetPagination
        filter_backends = (filters.OrderingFilter,)
        ordering_fields = ('id', 'name', 'update_ts')
        ordering = ('id',)
    
        # add a mapping of query_params to db_columns(queries)
        filter_mappings = {
            'id': 'id',
            'name': 'name__icontains',
            'team_id': 'teams',   # many-to-many relationship
            'install_ts': 'install_ts',
            'update_ts': 'update_ts',
            'update_ts__gte': 'update_ts__gte',
            'update_ts__lte': 'update_ts__lte',
        }
    
        # add validation on filters
        filter_validation_schema = players_query_schema
    
        def get_queryset(self):
            """
            Optionally restricts the queryset by filtering against
            query parameters in the URL.
            """
            query_params = self.request.query_params
            queryset = Player.objects.prefetch_related(
                'teams'  # use prefetch_related to minimize db hits.
            ).all()
    
            # This dict will hold filter kwargs to pass in to Django ORM calls.
            db_filters = {}
    
            # update filters dict with incoming query params and then pass as
            # **kwargs to queryset.filter()
             db_filters.update(
                self.get_queryset_filters(
                    query_params
                )
            )
            return queryset.filter(**db_filters)
    
    0 讨论(0)
提交回复
热议问题