您可能希望过滤查询集以确保仅返回与发出请求的当前经过身份验证的用户相关的结果。
您可以通过基于 的值进行过滤来做到这一点request.user 。
例如:
from myapp.models importPurchase
from myapp.serializers importPurchaseSerializer
from rest_framework import generics
classPurchaseList(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
returnPurchase.objects.filter(purchaser=user)
另一种过滤方式可能涉及基于 URL 的某些部分限制查询集。
例如,如果您的 URL 配置包含这样的条目:
re_path('^purchases/(?P<username>.+)/$',PurchaseList.as_view()),
然后,您可以编写一个返回由 URL 的用户名部分过滤的购买查询集的视图:
classPurchaseList(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']
returnPurchase.objects.filter(purchaser__username=username)
过滤初始查询集的最后一个示例是根据 url 中的查询参数确定初始查询集。
我们可以重写.get_queryset() 以处理诸如 之类的 URL ,并且仅当URL 中包含参数http://example.com/api/purchases?username=denvercoder9 时才过滤查询集:username
classPurchaseList(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 isnotNone:
queryset = queryset.filter(purchaser__username=username)
return queryset
该django-filter 库包含一个DjangoFilterBackend 类,该类支持 REST 框架的高度可定制的字段过滤。
要使用DjangoFilterBackend ,先安装django-filter 。
pip install django-filter
然后添加'django_filters' 到 Django 的INSTALLED_APPS :
INSTALLED_APPS =[
...
'django_filters',
...
]
您现在应该将过滤器后端添加到您的设置中:
REST_FRAMEWORK ={
'DEFAULT_FILTER_BACKENDS':['django_filters.rest_framework.DjangoFilterBackend']
}
或者将过滤器后端添加到单个视图或视图集。
from django_filters.rest_framework importDjangoFilterBackend
classUserListView(generics.ListAPIView):
...
filter_backends =[DjangoFilterBackend]
如果您只需要简单的基于相等的过滤,您可以filterset_fields 在视图或视图集上设置一个属性,列出您希望过滤的字段集。
classProductList(generics.ListAPIView):
queryset =Product.objects.all()
serializer_class =ProductSerializer
filter_backends =[DjangoFilterBackend]
filterset_fields =['category','in_stock']
这将自动FilterSet 为给定字段创建一个类,并允许您提出以下请求:
http://example.com/api/products?category=clothing&in_stock=True
对于更高级的过滤要求,您可以指定FilterSet 视图应使用的类。您可以在django-filter 文档中阅读更多关于FilterSet s 的信息。还建议您阅读DRF 集成部分。
该类SearchFilter 支持简单的基于单个查询参数的搜索,并且基于Django 管理员的搜索功能。
使用时,可浏览的 API 将包含一个SearchFilter 控件:
仅当视图具有属性集SearchFilter 时才会应用该类。search_fields 该search_fields 属性应该是模型上文本类型字段名称的列表,例如CharField 或TextField 。
from rest_framework import filters
classUserListView(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 .
- ‘^’ 以搜索开始。
- ‘=’ 完全匹配。
- ‘@’ 全文搜索。(目前只支持 Django 的PostgreSQL 后端。)
- ‘$’ 正则表达式搜索。
例如:
search_fields =['=username','=email']
默认情况下,搜索参数命名为'search' ,但这可能会被SEARCH_PARAM 设置覆盖。
要根据请求内容动态更改搜索字段,可以子类化SearchFilter 并覆盖该get_search_fields() 函数。例如,title 如果查询参数title_only 在请求中,以下子类将仅搜索:
from rest_framework import filters
classCustomSearchFilter(filters.SearchFilter):
def get_search_fields(self, view, request):
if request.query_params.get('title_only'):
return['title']
returnsuper().get_search_fields(view, request)
有关更多详细信息,请参阅Django 文档。
该类OrderingFilter 支持简单的查询参数控制的结果排序。
默认情况下,查询参数名为'ordering' ,但这可能会被ORDERING_PARAM 设置覆盖。
例如,按用户名排序用户:
http://example.com/api/users?ordering=username
客户端还可以通过在字段名称前加上“-”来指定反向排序,如下所示:
http://example.com/api/users?ordering=-username
也可以指定多个排序:
http://example.com/api/users?ordering=account,username
建议您明确指定 API 应在排序过滤器中允许哪些字段。您可以通过ordering_fields 在视图上设置属性来做到这一点,如下所示:
classUserListView(generics.ListAPIView):
queryset =User.objects.all()
serializer_class =UserSerializer
filter_backends =[filters.OrderingFilter]
ordering_fields =['username','email']
这有助于防止意外的数据泄漏,例如允许用户根据密码哈希字段或其他敏感数据进行排序。
如果您没有在视图上指定ordering_fields 属性,过滤器类将默认允许用户过滤由serializer_class 属性指定的序列化程序上的任何可读字段。
如果您确信视图使用的查询集不包含任何敏感数据,您还可以使用特殊值明确指定视图应允许对任何模型字段或查询集聚合进行排序'__all__' 。
classBookingsListView(generics.ListAPIView):
queryset =Booking.objects.all()
serializer_class =BookingSerializer
filter_backends =[filters.OrderingFilter]
ordering_fields ='__all__'
如果ordering 在视图上设置了属性,则这将用作默认排序。
通常,您可以通过order_by 在初始查询集上进行设置来控制它,但是ordering 在视图上使用参数允许您以一种随后可以作为上下文自动传递给呈现模板的方式指定排序。如果它们被用于对结果进行排序,这使得可以自动以不同的方式呈现列标题。
classUserListView(generics.ListAPIView):
queryset =User.objects.all()
serializer_class =UserSerializer
filter_backends =[filters.OrderingFilter]
ordering_fields =['username','email']
ordering =['username']
该ordering 属性可以是字符串或字符串的列表/元组。
您还可以提供自己的通用过滤后端,或编写可安装的应用程序供其他开发人员使用。
为此覆盖BaseFilterBackend ,并覆盖该.filter_queryset(self, request, queryset, view) 方法。该方法应返回一个新的过滤查询集。
除了允许客户端执行搜索和过滤之外,通用过滤器后端还可用于限制任何给定请求或用户应该可见的对象。
例子
例如,您可能需要将用户限制为只能查看他们创建的对象。
classIsOwnerFilterBackend(filters.BaseFilterBackend):
"""
Filter that only allows users to see their own objects.
"""
def filter_queryset(self, request, queryset, view):
return queryset.filter(owner=request.user)
我们可以通过覆盖get_queryset() 视图来实现相同的行为,但使用过滤器后端允许您更轻松地将此限制添加到多个视图,或将其应用于整个 API。
|