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
Django REST framework - filtering against query param
提问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)

