博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
rest_framework框架的认识
阅读量:2177 次
发布时间:2019-05-01

本文共 8150 字,大约阅读时间需要 27 分钟。

  
它是基于Django的,帮助我们快速开发符合RESTful规范的接口框架。

一  路由

  可以通过路由as_view()传参 根据请求方式的不同执行对应不同的方法

  在routers模块下 封装了很多关于路由的方法 , 最基础的BaseRouter类,给我提供自定制的接口。

  下面这个方法给我们提供了自动生成两条带参数的url

from rest_framework import routersfrom django.conf.urls import url, includefrom course.models import Coursefrom course.views import CourseViewrouters = routers.DefaultRouter()routers.register('Course', CourseView)urlpatterns = [    url(r'^', include(routers.urls)),]

二  视图

  帮助开发者提供了一些类,并在类中提供了多种方法供我们使用,下图是提供的主要的类以及继承关系。

   提供其他一些视图函数类,可以去源码里看。

三   版本控制

  下面以URL上控制版本为例

  1、添加配置

REST_FRAMEWORK = {    # 默认使用的版本控制类    'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',    # 允许的版本    'ALLOWED_VERSIONS': ['v1', 'v2'],    # 版本使用的参数名称    'VERSION_PARAM': 'version',    # 默认使用的版本    'DEFAULT_VERSION': 'v1',}

  2、设置路由

urlpatterns = [    #url(r'^admin/', admin.site.urls),        url(r'^api/(?P
\w+)/', include('api.urls')),]

  3、获取版本

    request.version 

四   认证

  rest_framework给我们提供了认证的接口,由BaseAuthentication类提供接口,也有一些封装好的认证类(请走入源码....)

  接口函数 authticate  认证成功返回一元组(user,token)分别赋值给request.user  和 request.auth

  下面是一个简单的认证示例

class Auth(BaseAuthentication):    def authenticate(self, request):        token = request.query_params.get('token')        obj = models.Token.objects.filter(token=token).first()        if not obj:            raise AuthenticationFailed({
'code': 1001, 'error': '认证失败'}) return (obj.user.username, obj)

  我们的认证类可以放在局部视图函数,也可以配置为全局认证。

# 局部视图函数认证class MyView(APIView):    authentication_classes = [Auth]    pass
# 全局配置 在settings.pyREST_FRAMEWORK = {    'DEFAULT_AUTHENTICATION_CLASSES': [Auth],}

五  权限

  由BasePermission类给我提供接口 接口函数为 has_permission  以及 has_object_permission

  有权限返回True 没有则返回False,默认的权限类为下图。

# 允许任何人访问class AllowAny(BasePermission):    """    Allow any access.    This isn't strictly required, since you could use an empty    permission_classes list, but it's useful because it makes the intention    more explicit.    """    def has_permission(self, request, view):        return True

  接口类为下图

class BasePermission(object):    """    A base class from which all permission classes should inherit.    """    def has_permission(self, request, view):        """        Return `True` if permission is granted, `False` otherwise.        """        # 这里写我们的权限逻辑        return True    def has_object_permission(self, request, view, obj):        """        Return `True` if permission is granted, `False` otherwise.        """        return True

  还封装了一些权限类,只允许admin用户访问的权限,只给认证的用户权限等等,请走源码........

六  频率

  基础的BaseThrottle类提供接口 接口函数为 allow_request,如果返回False则走wait

  SimpleRateThrottle类给我们提供了get_cache_key接口,继承这个类要写rate(num_request, duration)多长时间内访问次数

  实现原理如下代码:

class SimpleRateThrottle(BaseThrottle):    def allow_request(self, request, view):        if self.rate is None:            return True        self.key = self.get_cache_key(request, view)        if self.key is None:            return True        self.history = self.cache.get(self.key, [])        self.now = self.timer()       # 原理的实现逻辑        while self.history and self.history[-1] <= self.now -self.duration:            self.history.pop()        if len(self.history) >= self.num_requests:            return self.throttle_failure()        return self.throttle_success()

  这里就放这些~~具体~请大家走入源码.......

七   序列化

  对queryset序列化以及对请求数据格式验证。

  通常继承两个类 Serializer 以及 ModelSerializer  

  Serializer 序列化的每个字段都要自己写  ModelSerializer 会根据数据库表渲染所有字段 

  注意sourse 以及 钩子函数的应用 代码如下:

class CourseDetailModelSerializers(serializers.ModelSerializer):    title = serializers.CharField(source='course.name')    img = serializers.ImageField(source='course.course_img')    level = serializers.CharField(source='course.get_level_display')    recommends = serializers.SerializerMethodField()    chapters = serializers.SerializerMethodField()    def get_recommends(self, obj):        queryset = obj.recommend_courses.all()        return [{
'id': row.id, 'title': row.name} for row in queryset] def get_chapters(self, obj): queryset = obj.course.course_chapters.all() return [{
'id': row.id, 'name': row.name} for row in queryset] class Meta: model = CourseDetail fields = ['course', 'title', 'img', 'level', 'why_study', 'chapters', 'recommends']

 

八   分页

  对从数据库中获取到的数据进行分页处理  SQL --> limit  offset

    - 根据页码:http://www.myclass.com/api/v1/student/?page=1&size=10

    - 根据索引:http://www.myclass.com/api/v1/student/?offset=60&limit=10

    - 根据游标:http://www.myclass.com/api/v1/student/?page=erd8

  页码越大速度越慢,为什么怎么解决?

    - 原因:页码越大向后需要扫描的行数越多,因为每次都是从0开始扫描

    - 解决:

      - 限制当前显示的页数

      - 记录当前页面数据ID的最大值和最小值,再次分页时,根据ID进行筛选,在分页

  rest_framework 分页的配置

    -  全局分页配置  

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

    -  修改分页风格

class MyPagination(PageNumberPagination):    page_size = 100    page_size_query_param = 'page_size'    max_page_size = 1000# 然后在视图中使用.pagination_class属性调用该自定义类class MyView(generics.ListAPIView):    queryset = Billing.objects.all()    serializer_class = BillingRecordsSerializer    pagination_class = MyPagination# 或者是在settings.py中修改DEFAULT_PAGINATION_CLASSREST_FRAMEWORK = {    'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.MyPagination'}

  rest_framework给我提供的API

    1、 PageNumberPagination

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": [       …    ]}

   配置属性

    - page_size  每页显示对象的数量 如果设置了就重写PAGE_SIZE  

    - page_query_param  页面查询参数 指示分页空间的查询参数的名字

    - page_size_query_param  允许客户端根据每个请求设置页面大小 一般都为None

    - max_page_size  设置了page_size_query_param 才有意义 客户端请求页面中显示最大数量

    - last_page_strings 储存page_query_param参数请求过的值列表或元组

  2、LImitOffsetPagination

    路由配置以及返回类型

GET https://api.example.org/accounts/?limit=100&offset=400HTTP 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": [       …    ]}

   配置参数

    - page_size  每页显示对象的数量 如果设置了就重写PAGE_SIZE

    - default_limit: 如果客户端没有提供,则默认使用与PAGE_SIZE值一样。 

    - limit_query_param:表示限制查询参数的名字,默认为’limit’ 

    - offset_query_param:表示偏移参数的名字, 默认为’offset’ 

    - max_limit:允许页面中显示的最大数量,默认为None 

  3、CursorPagination

    - 基于游标的分页显示了一个不透明的“cursor”指示器,客户端可以使用它来浏览结果集。

    - 这种分页方式只允许用户向前或向后进行查询。并且不允许客户端导航到任意位置。

    - 基于游标的分页方式比较复杂,它要求结果集给出一个固定的顺序,并且不允许客户端任意的对结果集进行索引

    全局配置如下

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

    配置参数:

      - page_size:显示的最大条数 

      - cursor_query_param: 游标查询参数名,默认为’cursor’ 

      - ordering: 排序字段名的列表或者元组,例如ordering = ‘slug’,默认为-created 

  4、自定义分页

    - 继承pagination.BasePagination

    - 重写paginate_queryset(self, queryset, request, view=None)方法 ,

      初始化queryset对象,设置pagination实例  返回一个包含用户请求内容的可迭代对象 形成分页对象

    - 重写get_paginated_response(self, data)方法

      序列化请求页中所包含的对象,返回一个Response对象

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}

九  解析器

  默认的三个解析器 

    - JsonParser  Json数据解析器

    -  FormParser 和 MultiPartParser 一般同时使用

      Both request.data will be populated with a QueryDict. 官方文档的解释

DEFAULTS = {    # rest_framework  settings.py    'DEFAULT_PARSER_CLASSES': (        'rest_framework.parsers.JSONParser',        'rest_framework.parsers.FormParser',        'rest_framework.parsers.MultiPartParser'    ),}

 

十   渲染器

  默认的两个渲染器,一个是Json的,一个是用浏览器访问rest_framework自带的模板的

DEFAULTS = {    # rest_framework   setting.py    'DEFAULT_RENDERER_CLASSES': (        'rest_framework.renderers.JSONRenderer',        'rest_framework.renderers.BrowsableAPIRenderer',    ),}

 

转载地址:http://raykb.baihongyu.com/

你可能感兴趣的文章
阿里云《云原生》公开课笔记 第七章 应用编排与管理:Job和DaemonSet
查看>>
阿里云《云原生》公开课笔记 第八章 应用配置管理
查看>>
阿里云《云原生》公开课笔记 第九章 应用存储和持久化数据卷:核心知识
查看>>
linux系统 阿里云源
查看>>
国内外helm源记录
查看>>
牛客网题目1:最大数
查看>>
散落人间知识点记录one
查看>>
Leetcode C++ 随手刷 547.朋友圈
查看>>
手抄笔记:深入理解linux内核-1
查看>>
内存堆与栈
查看>>
Leetcode C++《每日一题》20200621 124.二叉树的最大路径和
查看>>
Leetcode C++《每日一题》20200622 面试题 16.18. 模式匹配
查看>>
Leetcode C++《每日一题》20200625 139. 单词拆分
查看>>
Leetcode C++《每日一题》20200626 338. 比特位计数
查看>>
Leetcode C++ 《拓扑排序-1》20200626 207.课程表
查看>>
Go语言学习Part1:包、变量和函数
查看>>
Go语言学习Part2:流程控制语句:for、if、else、switch 和 defer
查看>>
Go语言学习Part3:struct、slice和映射
查看>>
Go语言学习Part4-1:方法和接口
查看>>
Leetcode Go 《精选TOP面试题》20200628 69.x的平方根
查看>>