Python Django REST 框架 - 根据查询参数过滤

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/21182725/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-18 22:14:01  来源:igfitidea点击:

Django REST framework - filtering against query param

pythondjangoapirestdjango-rest-framework

提问by knowbody

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

所以我使用 REST 框架创建了我的“API”,现在尝试对其进行过滤。这就是我models.py或多或少的样子:

class Airline(models.Model):
    name = models.TextField()

class Workspace(models.Model):
    airline = models.ForeignKey(Airline)
    name = models.CharField(max_length=100)

class Passenger(models.Model):
    workspace = models.ForeignKey(Workspace)
    title = models.CharField(max_length=200)

So I would like to see in my JSON file "all passengers in particular workspace" or "all passengers in particular airline" etc.

所以我想在我的 JSON 文件中看到“特定工作区中的所有乘客”或“特定航空公司中的所有乘客”等。

Here is my, serializers.py

这是我的, serializers.py

class AirlineSerializer(serializers.ModelSerializer):
    class Meta:
        model = Airline


class WorkspaceSerializer(serializers.ModelSerializer):
    class Meta:
        model = Workspace


class PassengerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Passenger

And views.py:

并且views.py

class AirlineList(generics.ListCreateAPIView):
    model = Airline
    serializer_class = AirlineSerializer


class AirlineDetail(generics.RetrieveUpdateDestroyAPIView):
    model = Airline
    serializer_class = AirlineSerializer


class WorkspaceList(generics.ListCreateAPIView):
    model = Workspace
    serializer_class = WorkspaceSerializer


class WorkspaceDetail(generics.RetrieveUpdateDestroyAPIView):
    model = Workspace
    serializer_class = WorkspaceSerializer


class PassengerList(generics.ListCreateAPIView):
    model = Passenger
    serializer_class = PassengerSerializer


class PassengerDetail(generics.RetrieveUpdateDestroyAPIView):
    model = Passenger
    serializer_class = PassengerSerializer

It's my first time using REST framework, I have checked the docs, they helped me with what I've done so far, I would like to use

这是我第一次使用 REST 框架,我已经检查了文档,他们帮助我完成了迄今为止所做的工作,我想使用

Filtering against query parameter: http://www.django-rest-framework.org/api-guide/filtering/#filtering-against-query-parameters

根据查询参数过滤:http: //www.django-rest-framework.org/api-guide/filtering/#filtering-against-query-parameters

Can't really get it..

实在受不了。。

采纳答案by knowbody

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

所以使用@limelights 我设法做我想做的事,这是代码:

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

回答by Gabriel Muj

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

您只需使用文档http://www.django-rest-framework.org/api-guide/filtering/#djangofilterbackend中所述的 django-filter 包即可获得相同的功能

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'

在这种情况下,您必须使用 'workspace=1' 或 'workspace__airline=1' 进行过滤

回答by Manjit Kumar

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

这个django 应用程序以干净优雅的方式使用传入的查询参数对视图的查询集应用过滤器。

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

可以用pip安装 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

视图.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)