DRF框架学习(四)

简介: DRF框架学习(四)

DRF框架学习(四)

1.视图集对象的action属性

作用

获取现在要执行的是哪一种操作。

  1. self.action:是字符串类型,目的是获取所有执行的操作。

使用场景

重写 get_serializer_classget_queryset,根据不同的操作返回不同的序列化器类和不同的查询集。

  1. def get_serializer_class(self):
  2.    if self.action =='list':
  3.        # 返回list操作对应的序列化器类
  4.    elif self.action =='latest'
  5.        # 返回latest操作对应的序列化器类
  6.    else:
  7.        # 返回其他操作对应的序列化器类

  8. def get_queryset(self):
  9.    if self.action =='list':
  10.        # 返回list操作所使用的查询集
  11.    elif self.action =='latest':
  12.        # 返回latest操作所使用的查询集
  13.    else:
  14.        # 返回其他操作所使用的查询集

2.路由Router(urls文件中使用)

作用:(重点)

配合视图集进行使用,动态生成视图集中处理函数的url配置项。

使用:(重点)

1.创建router类的对象

  1. from restframe_work.routers importSimpleRouter,DefaultRouter
  2. router =SimpleRouter()或DefaultRouter()

2.注册视图集

  1. router.register(prefix,viewset,base_name)

例如:

  1. # 例如:
  2. from booktest.views importBookInfoViewSet
  3. router.register('books',views.BookInfoViewSet,base_name='books')

3.将生成的url配置项列表添加 urlpatterns中。

  1. urlpatterns += router.urls

注意点

指定Router生成视图集处理函数url配置项时,提取的参数正则表达式。

  1. lookup_value_regex ='\d+'

2.1视图集额外处理方法url配置项的生成

  • 需要给对应的方法添加action装饰器。
  1. # detail为False 表示路径名格式应该为 books/latest/
  2.    @action(methods=['get'], detail=False)
  3.    def latest(self, request):
  4.        """
  • 需要提取参数detail改为True,不需要提取参数的时候改为False
  • DefaultRouterSimpleRouter的区别是, DefaultRouter会多附带一个默认的API根视图,返回一个包含所有列表视图的超链接响应数据。 DefaultRouter创建的对象,在访问url地址的时候,我们都可以在后面加一个 .json,那么后台会给我们返回json格式的数据。

3.案例

写一个视图集,提供一下两个接口

1.获取所有的图书信息 GET/books/list

2.获取指定的图书信息 GET/books/(?P\<pk>\d+)/retrieve

  1. from rest_framework.authentication importSessionAuthentication
  2. from rest_framework.permissions importIsAuthenticated
  3. from rest_framework.generics importReadOnlyModelViewSet

  4. classBookInfoViewSet(ReadOnlyModelViewSet):
  5.    # 指定当前视图所使用的查询集
  6.    queryset =BookInfo.objects.all()
  7.    # 指定当前视图所使用的序列化器类
  8.    serializer_class =BookInfoSerializer
  9.    # 指定当前视图所使用的认证类
  10.    authentication_classes =[SessionAuthentication]
  11.    # 指定当前视图所使用的权限控制类
  12.    permission_classes =[IsAuthenticated]

url文件配置:

  1. from restframe_work.routers importDefaultRouter
  2. router =DefaultRouter()
  3. from booktest.views importBookInfoViewSet
  4. router.register('books',views.BookInfoViewSet,base_name='bookss')
  5. urlpatterns += router.urls

4.认证

DRF框架默认设置了两种全局认证方案,session认证和基本认证。

全局认证就是针对我们所有的接口。

认证需要配合权限来使用

4.1使用

DRF框架的默认全局认证方案如下,可对其进行修改,比如注释掉基本认证:

  1. REST_FRAMEWORK ={
  2.    'DEFAULT_AUTHENTICATION_CLASSES':(
  3.        'rest_framework.authentication.SessionAuthentication',  # session认证
  4.        'rest_framework.authentication.BasicAuthentication',   # 基本认证
  5.    )
  6. }

也可以在每个视图中通过设置authentication_classess属性来设置视图的认证方案:

  1. from rest_framework.authentication importSessionAuthentication,BasicAuthentication
  2. from rest_framework.views importAPIView

  3. classExampleView(APIView):
  4.    # 指定当前视图的认证方式(指定后不再使用全局的认证方案)
  5.    authentication_classes =(SessionAuthentication,BasicAuthentication)
  6.    ...

配合权限,如果认证失败会有两种可能的返回值:

  • 401 Unauthorized 未认证
  • 403 Permission Denied 权限被禁止

5.权限

权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。

  • 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
  • 在通过get_object()获取具体对象时,会进行对象访问权限的判断

DRF框架提供了四个权限控制类:

  • AllowAny允许所有用户(默认的)
  • IsAuthenticated仅通过认证的用户
  • IsAdminUser仅管理员用户
  • IsAuthenticatedOrReadOnly认证的用户可以完全操作,否则只能get读取

5.1使用

DRF框架的默认权限控制如下:

  1. 'DEFAULT_PERMISSION_CLASSES':(
  2.   'rest_framework.permissions.AllowAny',# 允许所有人
  3. )

可以在配置文件中设置权限管理类,如:

  1. REST_FRAMEWORK ={
  2.    # 权限设置
  3.    'DEFAULT_PERMISSION_CLASSES':(
  4.        'rest_framework.permissions.IsAuthenticated',# 仅仅允许认证用户进行访问
  5.    )
  6. }

也可以在具体的视图中通过 permission_classes属性来指定某个视图所使用的权限控制类,如:

  1. from rest_framework.permissions importIsAuthenticated
  2. from rest_framework.views importAPIView

  3. classExampleView(APIView):
  4.    #指定当前视图的权限控制类,指定以后不再使用全局设置
  5.    permission_classes =[IsAuthenticated]
  6.    # 还可以写成下面这个样子,但是注意逗号
  7.    permission_classes =(IsAuthenticated,)
  8.    ...

5.2自定义权限(了解即可)

如需自定义权限,需继承 rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部

  • .has_permission(self,request,view)

是否可以访问视图, view表示当前视图对象

  • .has_object_permission(self,request,view,obj)

是否可以访问数据对象, view表示当前视图, obj为数据对象


例如:

  1. classMyPermission(BasePermission):
  2.    def has_permission(self, request, view):
  3.        """判断对使用此权限类的视图是否有访问权限"""
  4.        # 任何用户对使用此权限类的视图都有访问权限
  5.        # True有权限,False没有权限
  6.        returnTrue

  7.    def has_object_permission(self, request, view, obj):
  8.        """判断对使用此权限类视图某个数据对象是否有访问权限"""
  9.        # 需求: 对id为1,3的数据对象有访问权限,其他的对象没有访问权限
  10.        if obj.id in(1,3):
  11.            returnTrue
  12.        returnFalse

  13. classBookInfoViewSet(ReadOnlyModelViewSet):
  14.    # 指定当前视图所使用的查询集
  15.    queryset =BookInfo.objects.all()
  16.    # 指定当前视图所使用的序列化器类
  17.    serializer_class =BookInfoSerializer
  18.    # 指定当前视图所使用的认证类
  19.    authentication_classes =[SessionAuthentication]
  20.    # 使用自定义的权限控制类
  21.    permission_classes =[MyPermission]

6.限流

作用:可以对接口访问的频次进行限制,以减轻服务器压力。

6.1 使用

DRF框架默认没有进行全局限流设置,但是提供了配置项,我们可以在配置文件中,使用 DEFAULT_THROTTLE_CLASSESDEFAULT_THROTTLE_RATES进行全局配置。

6.1.1 可选限流类

6.1.1.1 AnonRateThrottle

限制所有匿名未认证用户,使用IP区分用户。

使用 DEFAULT_THROTTLE_RATES['anon'] 来设置频次

6.1.1.2 UserRateThrottle

限制认证用户,使用User id 来区分。

使用 DEFAULT_THROTTLE_RATES['user'] 来设置频次

6.1.1.3 ScopedRateThrottle

限制用户对于每个视图的访问频次,使用ip或user id。

6.1.2 限流设置

6.1.2.1针对匿名用户和认证用户分别进行限流控制
  1. REST_FRAMEWORK ={
  2.    'DEFAULT_THROTTLE_CLASSES':(
  3.        # 针对未登录(匿名)用户的限流控制类
  4.        'rest_framework.throttling.AnonRateThrottle',
  5.        # 针对登录(认证)用户的限流控制类
  6.        'rest_framework.throttling.UserRateThrottle'
  7.    ),
  8.    # 指定限流频次
  9.    'DEFAULT_THROTTLE_RATES':{
  10.        # 认证用户的限流频次
  11.        'user':'5/minutes',
  12.        # 匿名用户的限流频次
  13.        'anon':'3/minutes',
  14.    },
  15. }

DEFAULT_THROTTLE_RATES 可以使用 second, minute, hourday来指明周期。

也可以在具体视图中通过throttle_classess属性来配置,如

  1. from rest_framework.throttling importUserRateThrottle
  2. from rest_framework.views importAPIView

  3. classExampleView(APIView):
  4.    throttle_classes =[UserRateThrottle]
  5.    ...
6.1.2.2针对匿名用户和认证用户进行统一的限流控制
  1. REST_FRAMEWORK ={
  2.    # 针对匿名用户和认证用户进行统一的限流控制
  3.    'DEFAULT_THROTTLE_CLASSES':(
  4.        'rest_framework.throttling.ScopedRateThrottle',
  5.    ),

  6.    # 设置限流频次选择项
  7.    'DEFAULT_THROTTLE_RATES':{
  8.        'upload':'3/minute',
  9.        'contacts':'5/minute'
  10.    },
  11. }

进行了上面的配置之后,其实我们的视图还没有限流的效果,如果想实现限流,还需进行下列操作:

  1. classContactListView(APIView):
  2.    # 指定限流频次选择项
  3.    throttle_scope ='contacts'
  4.    ...
  5.    pass


  6. classUploadView(APIView):
  7.    throttle_scope ='uploads'
  8.    ...
  9.    pass

7.过滤

对于列表数据可能需要根据字段进行过滤,我们可以通过添加django-fitlter扩展来增强支持。

  1. pip install django-filter

在配置文件中增加过滤后端的设置:

  1. INSTALLED_APPS =[
  2.    ...
  3.    'django_filters',  # 需要注册应用,
  4. ]
  5. # 过滤
  6. REST_FRAMEWORK ={
  7.    'DEFAULT_FILTER_BACKENDS':('django_filters.rest_framework.DjangoFilterBackend',)
  8. }

在视图中添加filter_fields属性,指定可以过滤的字段

需求:写一个类视图,提供1个接口

1.获取所有的图书信息 GET/books/

  1. classBookListView(ListAPIView):
  2.    queryset =BookInfo.objects.all()
  3.    serializer_class =BookInfoSerializer
  4.    # 指定过滤字段,根据书名和阅读量过滤,还可以添加其他的过滤字段
  5.    filter_fields =('btitle','bread')

  6. # 127.0.0.1:8000/books/?btitle=西游记

8.排序

对于列表数据,REST framework提供了OrderingFilter过滤器来帮助我们快速指明数据按照指定字段进行排序。

8.1使用方法:

在类视图中设置filter_backends,使用 rest_framework.filters.OrderingFilter过滤器,REST framework会在请求的查询字符串参数中检查是否包含了ordering参数,如果包含了ordering参数,则按照ordering参数指明的排序字段对数据集进行排序。

前端可以传递的ordering参数的可选字段值需要在ordering_fields中指明。

示例

默认是升序,如果想要实现降序的效果,那么在传入查询字符串的时候在字段名前加-,如下:

  1. classBookListView(ListAPIView):
  2.    queryset =BookInfo.objects.all()
  3.    serializer_class =BookInfoSerializer
  4.    filter_backends =[OrderingFilter]
  5.    # 根据指定字段进行排序
  6.    ordering_fields =('id','bread','bpub_date')
  7. # 127.0.0.1:8000/books/?ordering=-bread

9.分页(重点)

REST framework提供了分页的支持。

我们可以在配置文件中设置全局的分页方式,如:

  1. REST_FRAMEWORK ={
  2.    'DEFAULT_PAGINATION_CLASS':  '<全局分页类>',
  3.    'PAGE_SIZE':<页容量>  
  4. }

如:

  1. REST_FRAMEWORK ={
  2.    'DEFAULT_PAGINATION_CLASS':  'rest_framework.pagination.PageNumberPagination',
  3.    'PAGE_SIZE':5  # 每页数目
  4. }

9.1可选分页类

9.1.1PageNumberPagination

?page=<页码>

前端访问网址形式:

  1. GET  http://api.example.org/books/?page=4

可以在子类中定义的属性:

  • page_size 每页数目
  • pagequeryparam 前端发送的页数关键字名,默认为"page"
  • pagesizequery_param 前端发送的每页数目关键字名,默认为None
  • maxpagesize 前端最多能设置的每页数量

9.1.2LimitOffsetPagination

?offset=<偏移量>&limit=<数据条数>

前端访问网址形式:

  1. GET http://api.example.org/books/?limit=100&offset=400

可以在子类中定义的属性:

  • default_limit 默认限制,默认值与 PAGE_SIZE设置一直
  • limitqueryparam limit参数名,默认'limit'
  • offsetqueryparam offset参数名,默认'offset'
  • max_limit 最大limit限制,默认None

注意:如果在视图内关闭分页功能,只需在视图内设置

  1. pagination_class =None

9.2自定义分页类

也可通过自定义Pagination类,来为视图添加不同分页行为。在视图中通过 pagination_clas属性来指明。

  1. classStandardResultPagination(PageNumberPagination):
  2.    # 分页默认页容量
  3.    page_size =3
  4.    # 获取分页数据时,传递也容量的参数名称
  5.    page_size_query_param ='page_size'
  6.    # 分页时最大页容量,但是不能超过最大的页容量
  7.    max_page_size =5
  8. classBookListView(ListAPIView):
  9.    queryset =BookInfo.objects.all()
  10.    serializer_class =BookInfoSerializer
  11.    # 指定当前视图所使用的分页类
  12.    pagination_class =StandardResultPagination

通过 http://api.example.org/books/?page=<页码>&page_size=<页容量> 进行访问。

注意:视图关闭分页

  1. pagination_class =None

10.异常处理(重点)

REST framework提供了异常处理,可以出来以下异常:

  • APIException 所有异常的父类
  • ParseError 解析错误
  • AuthenticationFailed 认证失败
  • NotAuthenticated 尚未认证
  • PermissionDenied 权限决绝
  • NotFound 未找到
  • MethodNotAllowed 请求方式不支持
  • NotAcceptable 要获取的数据格式不支持
  • Throttled 超过限流次数
  • ValidationError 校验失败

10.1异常处理设置

DRF框架的默认异常处理设置如下:

  1. REST_FRAMEWORK ={
  2.    'EXCEPTION_HANDLER':'rest_framework.views.exception_handler'
  3. }

默认使用 rest_framework.views.exception_handler模块下的 exception_handler函数进行异常处理。

10.2自定义异常处理

10.2.1自定义DRF框架异常处理函数

1.自定义异常处理函数

2.设置EXCEPTION_HANDLER配置项

10.2.2详解

可以在DRF框架异常处理函数的基础上,补充一些其他的异常处理,比如数据库处理:

  1. from rest_framework.views import exception_handler as drf_exception_handler
  2. from rest_framework import status
  3. from django.db importDatabaseError

  4. def exception_handler(exc, context):
  5.    # 先调用DRF框架的默认异常处理函数
  6.    response = drf_exception_handler(exc, context)

  7.    if response isNone:
  8.        view = context['view']
  9.        # 补充数据库的异常处理
  10.        if isinstance(exc,DatabaseError):
  11.            print('[%s]: %s'%(view, type(exc)))
  12.            response =Response({'detail':'服务器内部错误'}, status=status.HTTP_507_INSUFFICIENT_STORAGE)

  13.    return response

在配置文件中声明自定义的异常处理:

  1. REST_FRAMEWORK ={
  2.    'EXCEPTION_HANDLER':'booktest.utils.exceptions.exception_handler'
  3. }
相关文章
|
4月前
|
Python API 网络架构
Django实践-10RESTful架构和DRF入门
Django实践-10RESTful架构和DRF入门
Django实践-10RESTful架构和DRF入门
|
1月前
|
前端开发 API 网络架构
Python 如何开发出RESTful Web接口,DRF框架助力灵活实现!
Python 如何开发出RESTful Web接口,DRF框架助力灵活实现!
|
7月前
|
JSON API 数据库
DRF框架学习(二)
DRF框架学习(二)
|
7月前
|
JSON 前端开发 API
DRF框架学习(一)
DRF框架学习(一)
|
7月前
|
JSON 前端开发 数据库
DRF框架学习(三)
DRF框架学习(三)
|
7月前
|
JSON 前端开发 Android开发
DRF框架使用时的一些注意点
DRF框架使用时的一些注意点
|
11月前
|
测试技术 Apache
学习新框架的方法
官网:xxxx.apache.org apache基金会顶级项目 英文 平时的积累 云笔记:记下来
61 0
|
JSON 算法 API
|
JSON API 数据库
|
API 数据格式