REST 框架的通用列表视图的默认行为是返回模型管理器的整个查询集。通常,您希望 API 限制查询集返回的项目。
筛选子类的任何视图的查询集的最简单方法是重写该方法。GenericAPIView.get_queryset()
重写此方法允许您以多种不同的方式自定义视图返回的查询集。
您可能希望筛选查询集,以确保仅返回与发出请求的当前经过身份验证的用户相关的结果。
为此,可以基于用户值进行筛选。request.user
例如:
from myapp.models import Purchase
from myapp.serializers import PurchaseSerializer
from rest_framework import generics
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases
for the currently authenticated user.
"""
user = self.request.user
return Purchase.objects.filter(purchaser=user)
一种筛选方式可能涉及根据 URL 的某些部分限制查询集。
例如,如果您的 URL 配置包含如下条目:
re_path('^purchases/(?P.+)/$', PurchaseList.as_view()),
然后,您可以编写一个视图,返回按 URL 的用户名部分筛选查询集:
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
This view should return a list of all the purchases for
the user as determined by the username portion of the URL.
"""
username = self.kwargs['username']
return Purchase.objects.filter(purchaser__username=username)
筛选初始查询集的最后一个示例是根据 url 中的查询参数确定初始查询集。
我们可以覆盖以处理 URL,例如 ,并且仅当参数包含在 URL 中时才筛选查询集:
class PurchaseList(generics.ListAPIView):
serializer_class = PurchaseSerializer
def get_queryset(self):
"""
Optionally restricts the returned purchases to a given user,
by filtering against a `username` query parameter in the URL.
"""
queryset = Purchase.objects.all()
username = self.request.query_params.get('username')
if username is not None:
queryset = queryset.filter(purchaser__username=username)
return queryset
除了能够重写默认查询集之外,REST 框架还包括对通用筛选后端的支持,这些后端允许您轻松构造复杂的搜索和筛选器。
通用筛选器还可以在可浏览 API 和管理 API 中显示为 HTML 控件。
安装对应的包:pip install django-filter
INSTALLED_APPS = [
...
'django_filters',
...
]
REST_FRAMEWORK = {
'DEFAULT_FILTER_BACKENDS': ['django_filters.rest_framework.DjangoFilterBackend']
}
from django_filters.rest_framework import DjangoFilterBackend
class UserListView(generics.ListAPIView):
...
filter_backends = [DjangoFilterBackend]
class ProductList(generics.ListAPIView):
queryset = Product.objects.all()
serializer_class = ProductSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = ['category', 'in_stock']
http://example.com/api/products?category=clothing&in_stock=True
仅当视图具有属性集时,才会应用该类。该属性应是模型上文本类型字段的名称列表,例如
from rest_framework import filters
class UserListView(generics.ListAPIView):
queryset = User.objects.all()
serializer_class = UserSerializer
filter_backends = [filters.SearchFilter]
search_fields = ['username', 'email']
http://example.com/api/users?search=russell
还可以使用查找 API 双下划线表示法对 ForeignKey 或 ManyToManyField 执行相关查找:
search_fields = ['username', 'email', 'profile__profession']
对于 JSONField 和 HStoreField 字段,您可以使用相同的双下划线表示法根据数据结构中的嵌套值进行查找:
search_fields = ['data__breed', 'data__owner__other_pets__0__name']
默认情况下,搜索将使用不区分大小写的部分匹配项。搜索参数可能包含多个搜索词,这些搜索词应以空格和/或逗号分隔。如果使用多个搜索词,则仅当所有提供的词都匹配时,才会在列表中返回对象。
搜索行为可能会因在 前面加上各种字符而受到限制。search_fields
search_fields = ['=username', '=email']
默认情况下,搜索参数名为 ,但该设置可能会覆盖该参数。
若要根据请求内容动态更改搜索字段,可以对 函数进行子类化并覆盖该函数。例如,如果查询参数在请求中,则以下子类将仅搜索
from rest_framework import filters
class CustomSearchFilter(filters.SearchFilter):
def get_search_fields(self, view, request):
if request.query_params.get('title_only'):
return ['title']
return super().get_search_fields(view, request)