DRF-过滤

过滤当前用户

您可能希望过滤查询集以确保仅返回与发出请求的当前经过身份验证的用户相关的结果。

您可以通过基于 的值进行过滤来做到这一点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 的某些部分限制查询集。

例如,如果您的 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 文档中阅读更多关于FilterSets 的信息。还建议您阅读DRF 集成部分。

搜索过滤器

该类SearchFilter支持简单的基于单个查询参数的搜索,并且基于Django 管理员的搜索功能

使用时,可浏览的 API 将包含一个SearchFilter控件:

搜索过滤器

仅当视图具有属性集SearchFilter时才会应用该类。search_fieldssearch_fields属性应该是模型上文本类型字段名称的列表,例如CharFieldTextField

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']

对于JSONFieldHStoreField字段,您可以使用相同的双下划线表示法基于数据结构中的嵌套值进行过滤:

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。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值