zoukankan      html  css  js  c++  java
  • Django REST Framework API Guide 08

    1、Filtering

    2、Pagination

    FIltering

    GenericAPIView的子类筛选queryset的简单方法是重写.get_quueryset()方法。

    1、根据当前用户进行筛选  # self.request.user
    2、根据当前URL  # self.kwargs, url('^purchases/(?P<username>.+)/$', PurchaseList.as_view()),
    3、根据当前url查询参数  # self.request.query_params
    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)

    API Guide

    REST框架也包含支持通用筛选后端允许你构建复杂的查询和筛选,此时需要先引出DjangoFilterBackend模块

    需要先安装django_filters,并将它添加到INSTALLED_APPS

    pip install django-filter

    DjangoFilterBackend

    1、可以用全局设置

    REST_FRAMEWORK = {
        'DEFAULT_FILTER_BACKENDS': ('django_filters.rest_framework.DjangoFilterBackend',)
    }

    2、也可以对每个使用CBV格式的继承自GenericAPIView类的视图或者视图集单独设置。

    from django_filters.rest_framework import DjangoFilterBackend
    
    class UserListView(generics.ListAPIView):
        ...
        filter_backends = (DjangoFilterBackend,)

    如果是需要简单的基于等式的过滤,你在工作视图类或者视图集类上可以设置filter_fields属性

    class ProductList(generics.ListAPIView):
        queryset = Product.objects.all()
        serializer_class = ProductSerializer
        filter_backends = (DjangoFilterBackend,)
        filter_fields = ('category', 'in_stock')

    这将允许你对提供的字段创建一个FIlterSet类,允许你的request如下

    http://example.com/api/products?category=clothing&in_stock=True

    SearchFilter

    SearchFilter类支持单独的查询参数查询,基于django admin的查询功能。

    需要在类上设置search_fields属性集,必须是模型上的一组字段名

    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

    你也可以添加一个相关外键或者多对多字段查找

    search_fields = ('username', 'email', 'profile__profession')

    默认情况下,搜索将使用不区分大小写的部分匹配。搜索参数可以包含多个搜索项,它们应该是空白和/或逗号分隔的。如果使用多个搜索项,那么只有在所有提供的条件匹配时,对象才会返回到列表中。

    搜索行为可以通过向search_fields字段添加各种字符来加以限制。

    • '^' Starts-with search.
    • '=' Exact matches.
    • '@' Full-text search. (Currently only supported Django's MySQL backend.)
    • '$' Regex search.
    search_fields = ('=username', '=email')

    默认查询参数是search,你可以用SEARCH_PARAM来改

    OrderingFilter

    默认url参数ordering,可以通过ORDERING_PARAM设置来重写。

    1 http://example.com/api/users?ordering=username
    2 http://example.com/api/users?ordering=-username
    3 http://example.com/api/users?ordering=account,username

    指定排序字段,可以通过类上的ordering_fields属性完成

    class UserListView(generics.ListAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        filter_backends = (filters.OrderingFilter,)
        ordering_fields = ('username', 'email')

    如果没有设置,也可以在serializer_class里面设置,如果您确信视图使用的查询集不包含任何敏感数据,那么还可以通过使用特殊值'__all__',显式地指定视图应该允许对任何模型字段或查询集聚合进行排序。

    class BookingsListView(generics.ListAPIView):
        queryset = Booking.objects.all()
        serializer_class = BookingSerializer
        filter_backends = (filters.OrderingFilter,)
        ordering_fields = '__all__'

    指定一个默认排序

    如果类上设置了ordering属性,将会被用来当做默认的排序。通常,您可以通过在初始查询集上设置order_by来控制这一点,但是使用视图上的ordering参数允许您以某种方式指定顺序,然后它可以自动地作为上下文传递到呈现的模板。如果列标题被用于排序结果,则可以自动呈现不同的列标题。

    class UserListView(generics.ListAPIView):
        queryset = User.objects.all()
        serializer_class = UserSerializer
        filter_backends = (filters.OrderingFilter,)
        ordering_fields = ('username', 'email')
        ordering = ('username',)

    DjangoObjectPermissionsFilter

    DjangoObjectPermissionsFilter意在跟django-guardian包一起使用,添加客制化的视图权限。过滤器确保querysets只返回用户有合适视图权限的对象。

    想要使用DjangoObjectPermissionsFilter,你也要添加一个合适的对象权限类,确保有合适权限的用户可以操作实例。最简单的方法就是使用DjangoObjectPermissionsFilter子类,并添加视图权限到perms_map属性。使用DjangoObjectPermissionsFilter和DjangoobjectPermissions的完整示例。

    permissions.py

    class CustomObjectPermissions(permissions.DjangoObjectPermissions):
        """
        Similar to `DjangoObjectPermissions`, but adding 'view' permissions.
        """
        perms_map = {
            'GET': ['%(app_label)s.view_%(model_name)s'],
            'OPTIONS': ['%(app_label)s.view_%(model_name)s'],
            'HEAD': ['%(app_label)s.view_%(model_name)s'],
            'POST': ['%(app_label)s.add_%(model_name)s'],
            'PUT': ['%(app_label)s.change_%(model_name)s'],
            'PATCH': ['%(app_label)s.change_%(model_name)s'],
            'DELETE': ['%(app_label)s.delete_%(model_name)s'],
        }

    views.py

    class EventViewSet(viewsets.ModelViewSet):
        """
        Viewset that only lists events if user has 'view' permissions, and only
        allows operations on individual events if user has appropriate 'view', 'add',
        'change' or 'delete' permissions.
        """
        queryset = Event.objects.all()
        serializer_class = EventSerializer
        filter_backends = (filters.DjangoObjectPermissionsFilter,)
        permission_classes = (myapp.permissions.CustomObjectPermissions,)

    Pagination

    当你使用通用视图或者视图集是分页才会自动执行。如果你使用的是一个常规的APIView,你需要自己去调用分页的API来确保结果是被分页好的响应。可以看一下mixins.ListModelMixingenerics.GenericAPIView的源码,可以通过设置分页的类为None来关闭分页。

    设置分页样式

    全局设置

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
        'PAGE_SIZE': 100
    }

    你也可以单独设置独立的视图的pagination_class属性

    修改分页样式

    class LargeResultsSetPagination(PageNumberPagination):
        page_size = 1000
        page_size_query_param = 'page_size'
        max_page_size = 10000
    
    class StandardResultsSetPagination(PageNumberPagination):
        page_size = 100
        page_size_query_param = 'page_size'
        max_page_size = 1000

    然后你可以应用新的样式通过在视图上使用.pagination_class属性

    class BillingRecordsView(generics.ListAPIView):
        queryset = Billing.objects.all()
        serializer_class = BillingRecordsSerializer
        pagination_class = LargeResultsSetPagination

    或者你也可以把这个分页样式类设置成全局的

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.StandardResultsSetPagination'
    }

    API Reference

    PageNumberPagination

    此分页样式允许传入一个单独的page数字在请求中

    GET https://api.example.org/accounts/?page=4

    响应:

    HTTP 200 OK
    {
        "count": 1023
        "next": "https://api.example.org/accounts/?page=5",
        "previous": "https://api.example.org/accounts/?page=3",
        "results": [
           …
        ]
    }

    全局设置PageNumberPagination,并设置PAGE_SIZE:

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.PageNumberPagination',
        'PAGE_SIZE': 100
    }

    配置

    PageNumberPagination类包含了很多属性,可以通过重写属性或者方法改变分页风格

    1、django_paginator_class  # 使用Django Paginator 类,默认django.core.paginator.Paginator
    2、page_size  # 每页显示条数
    3、page_query_param  # 一个字符串值,指示要用于分页控件的查询参数的名称。
    4、page_size_query_param  # 默认为空,如果设置,则是一个字符串值,指示允许客户端根据每个请求设置页面大小的查询参数的名称。
    5、max_page_size  # 如果设置,这是一个指示最大允许请求页面大小的数值。此属性仅在page_size_query_param也被设置时有效。
    6、last_page_strings  # 一个字符串值的列表或元组,指示可能与page_query_param一起用于请求集合中的最终页的值。默认('last', )
    7、template  # 可视化API的模板。默认"rest_framework/pagination/numbers.html"

    LimitOffsetPagination

    这种分页样式反映了查找多个数据库记录时使用的语法。客户端包括“限制”和“偏移”查询参数。该限制指示要返回的最大项目数,并且等同于其他样式中的page_size大小。偏移量指示查询相对于未分页项目的完整集合的起始位置。

    GET https://api.example.org/accounts/?limit=100&offset=400
    HTTP 200 OK
    {
        "count": 1023
        "next": "https://api.example.org/accounts/?limit=100&offset=500",
        "previous": "https://api.example.org/accounts/?limit=100&offset=300",
        "results": [
           …
        ]
    }

    配置

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination'
    }

    自定义分页样式

    创建自定义的分页序列化类,需要继承pagination.BasePagination并重写.paginate_queryset(self, queryset, request, view=None)和get_paginated_response(self, data)方法

    1、paginate_queryset  # 通过初始化queryset返回一个可迭代的对象仅包含请求页面的数据
    2、get_paginated_response  # 通过序列化页面的数据,返回一个Response实例

    假设我们想用修改的格式替换默认的分页输出样式,该格式包括嵌套的“links”键中的下一链接和先前链接。我们可以指定像这样的自定义分页类:

    class CustomPagination(pagination.PageNumberPagination):
        def get_paginated_response(self, data):
            return Response({
                'links': {
                    'next': self.get_next_link(),
                    'previous': self.get_previous_link()
                },
                'count': self.page.paginator.count,
                'results': data
            })

    设置

    REST_FRAMEWORK = {
        'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
        'PAGE_SIZE': 100
    }
  • 相关阅读:
    ORA16014 与 ORA00312
    ORA26687
    ORA32004问题解决
    ORA23616:执行块5失败
    Streams实践之Schemas级复制
    Streams FAQ
    ORA23622: 正在执行操作SYS.DBMS_STREAMS_ADM.MAINTAIN_GLOBAL
    为什么白帽SEO更好?
    HyperV虚拟机安装及网卡无法找到,驱动无法安装解决办法
    Memcahed分布式缓存服务替换Session解决方案——简单介绍[转]
  • 原文地址:https://www.cnblogs.com/wuzdandz/p/9675173.html
Copyright © 2011-2022 走看看