rest_framework框架的认识

打印 上一主题 下一主题

主题 954|帖子 954|积分 2866


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


<div id="cnblogs_post_body" 一  路由button  title="显示目录导航"/button/h3p  可以通过路由as_view()传参 根据请求方式的不同执行对应不同的方法/pp  在routers模块下 封装了很多关于路由的方法 , 最基础的BaseRouter类,给我提供自定制的接口。/pp  下面这个方法给我们提供了自动生成两条带参数的url/pa title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/a
  1. from rest_framework import routers
  2. from django.conf.urls import url, include
  3. from course.models import Course
  4. from course.views import CourseView
  5. routers = routers.DefaultRouter()
  6. routers.register('Course', CourseView)
  7. urlpatterns = [
  8.     url(r'^', include(routers.urls)),
  9. ]
复制代码
a title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/ah3二  视图button  title="显示目录导航"/button/h3p  帮助开发者提供了一些类,并在类中提供了多种方法供我们使用,下图是提供的主要的类以及继承关系。img src="https://images2018.cnblogs.com/blog/1349080/201807/1349080-20180703151758766-93913407.png" alt="" /pp   提供其他一些视图函数类,可以去源码里看。/ph3三   版本控制button  title="显示目录导航"/button/h3p  下面以URL上控制版本为例/pp  1、添加配置/pa title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/a
  1. REST_FRAMEWORK = {
  2.     # 默认使用的版本控制类
  3.     'DEFAULT_VERSIONING_CLASS': 'rest_framework.versioning.URLPathVersioning',
  4.     # 允许的版本
  5.     'ALLOWED_VERSIONS': ['v1', 'v2'],
  6.     # 版本使用的参数名称
  7.     'VERSION_PARAM': 'version',
  8.     # 默认使用的版本
  9.     'DEFAULT_VERSION': 'v1',
  10. }
复制代码
a title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/ap  2、设置路由/p
  1. urlpatterns = [
  2.     #url(r'^admin/', admin.site.urls),
  3.         url(r'^api/(?P<version>\w+)/', include('api.urls')),
  4. ]
复制代码
p  3、获取版本/pp    request.version /ph3四   认证button  title="显示目录导航"/button/h3p  rest_framework给我们提供了认证的接口,由BaseAuthentication类提供接口,也有一些封装好的认证类(请走入源码....)/pp  接口函数 authticate  认证成功返回一元组(user,token)分别赋值给request.user  和 request.auth/pp  下面是一个简单的认证示例/pa title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/a
  1. class Auth(BaseAuthentication):
  2.     def authenticate(self, request):
  3.         token = request.query_params.get('token')
  4.         obj = models.Token.objects.filter(token=token).first()
  5.         if not obj:
  6.             raise AuthenticationFailed({'code': 1001, 'error': '认证失败'})
  7.         return (obj.user.username, obj)
复制代码
a title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/ap  我们的认证类可以放在局部视图函数,也可以配置为全局认证。/p
  1. # 局部视图函数认证
  2. class MyView(APIView):
  3.     authentication_classes = [Auth]
  4.     pass
复制代码
  1. # 全局配置 在settings.py
  2. REST_FRAMEWORK = {
  3.     'DEFAULT_AUTHENTICATION_CLASSES': [Auth],
  4. }
复制代码
h3五  权限button  title="显示目录导航"/button/h3p  由BasePermission类给我提供接口 接口函数为 has_permission  以及 has_object_permission/pp  有权限返回True 没有则返回False,默认的权限类为下图。/pa title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/a
  1. # 允许任何人访问
  2. class AllowAny(BasePermission):
  3.     """
  4.     Allow any access.
  5.     This isn't strictly required, since you could use an empty
  6.     permission_classes list, but it's useful because it makes the intention
  7.     more explicit.
  8.     """
  9.     def has_permission(self, request, view):
  10.         return True
复制代码
a title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/ap  接口类为下图/pa title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/a
  1. class BasePermission(object):
  2.     """
  3.     A base class from which all permission classes should inherit.
  4.     """
  5.     def has_permission(self, request, view):
  6.         """
  7.         Return `True` if permission is granted, `False` otherwise.
  8.         """
  9.         # 这里写我们的权限逻辑
  10.         return True
  11.     def has_object_permission(self, request, view, obj):
  12.         """
  13.         Return `True` if permission is granted, `False` otherwise.
  14.         """
  15.         return True
复制代码
a title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/ap  还封装了一些权限类,只允许admin用户访问的权限,只给认证的用户权限等等,请走源码......../ph3六  频率button  title="显示目录导航"/button/h3p  基础的BaseThrottle类提供接口 接口函数为 allow_request,如果返回False则走wait/pp  SimpleRateThrottle类给我们提供了get_cache_key接口,继承这个类要写rate(num_request, duration)多长时间内访问次数/pp  实现原理如下代码:/pa title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/a
  1. class SimpleRateThrottle(BaseThrottle):
  2.     def allow_request(self, request, view):
  3.         if self.rate is None:
  4.             return True
  5.         self.key = self.get_cache_key(request, view)
  6.         if self.key is None:
  7.             return True
  8.         self.history = self.cache.get(self.key, [])
  9.         self.now = self.timer()
  10.        # 原理的实现逻辑
  11.         while self.history and self.history[-1] <= self.now -self.duration:
  12.             self.history.pop()
  13.         if len(self.history) >= self.num_requests:
  14.             return self.throttle_failure()
  15.         return self.throttle_success()
复制代码
a title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/ap  这里就放这些~~具体~请大家走入源码......./ph3七   序列化button  title="显示目录导航"/button/h3p  对queryset序列化以及对请求数据格式验证。/pp  通常继承两个类 Serializer 以及 ModelSerializer  /pp  Serializer 序列化的每个字段都要自己写  ModelSerializer 会根据数据库表渲染所有字段 /pp  注意sourse 以及 钩子函数的应用 代码如下:/pa title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/a
  1. class CourseDetailModelSerializers(serializers.ModelSerializer):
  2.     title = serializers.CharField(source='course.name')
  3.     img = serializers.ImageField(source='course.course_img')
  4.     level = serializers.CharField(source='course.get_level_display')
  5.     recommends = serializers.SerializerMethodField()
  6.     chapters = serializers.SerializerMethodField()
  7.     def get_recommends(self, obj):
  8.         queryset = obj.recommend_courses.all()
  9.         return [{'id': row.id, 'title': row.name} for row in queryset]
  10.     def get_chapters(self, obj):
  11.         queryset = obj.course.course_chapters.all()
  12.         return [{'id': row.id, 'name': row.name} for row in queryset]
  13.     class Meta:
  14.         model = CourseDetail
  15.         fields = ['course', 'title', 'img', 'level', 'why_study', 'chapters', 'recommends']
复制代码
a title="复制代码" rel="noopener"img src="https://common.cnblogs.com/images/copycode.gif" alt="复制代码"/ap /ph3八   分页button  title="显示目录导航"/button/h3p  对从数据库中获取到的数据进行分页处理  SQL --> limit  offset</p>    - 根据页码: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 分页的配置
    -  全局分页配置  
  1. # settings.py
  2. REST_FRAMEWORK = {
  3.     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.LimitOffsetPagination',
  4.     'PAGE_SIZE': 100
  5. }
复制代码
    -  修改分页风格
  1. class MyPagination(PageNumberPagination):
  2.     page_size = 100
  3.     page_size_query_param = 'page_size'
  4.     max_page_size = 1000
  5. # 然后在视图中使用.pagination_class属性调用该自定义类
  6. class MyView(generics.ListAPIView):
  7.     queryset = Billing.objects.all()
  8.     serializer_class = BillingRecordsSerializer
  9.     pagination_class = MyPagination
  10. # 或者是在settings.py中修改DEFAULT_PAGINATION_CLASS
  11. REST_FRAMEWORK = {
  12.     'DEFAULT_PAGINATION_CLASS': 'apps.core.pagination.MyPagination'
  13. }
复制代码
  rest_framework给我提供的API
    1、 PageNumberPagination
?
1GET https://api.example.org/accounts/?page=4
    响应对象 
  1. HTTP 200 OK
  2. {
  3.     "count": 1023
  4.     "next": "https://api.example.org/accounts/?page=5",
  5.     "previous": "https://api.example.org/accounts/?page=3",
  6.     "results": [
  7.        …
  8.     ]
  9. }
复制代码
   配置属性
    - 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
    路由配置以及返回类型
  1. GET https://api.example.org/accounts/?limit=100&offset=400
  2. HTTP 200 OK
  3. {
  4.     "count": 1023
  5.     "next": "https://api.example.org/accounts/?limit=100&offset=500",
  6.     "previous": "https://api.example.org/accounts/?limit=100&offset=300",
  7.     "results": [
  8.        …
  9.     ]
  10. }
复制代码
   配置参数
    - page_size  每页显示对象的数量 如果设置了就重写PAGE_SIZE
    - default_limit: 如果客户端没有提供,则默认使用与PAGE_SIZE值一样。 
    - limit_query_param:表示限制查询参数的名字,默认为’limit’ 
    - offset_query_param:表示偏移参数的名字, 默认为’offset’ 
    - max_limit:允许页面中显示的最大数量,默认为None 
  3、CursorPagination
    - 基于游标的分页显示了一个不透明的“cursor”指示器,客户端可以使用它来浏览结果集。
    - 这种分页方式只允许用户向前或向后进行查询。并且不允许客户端导航到任意位置。
    - 基于游标的分页方式比较复杂,它要求结果集给出一个固定的顺序,并且不允许客户端任意的对结果集进行索引
    全局配置如下
  1. REST_FRAMEWORK = {
  2.     'DEFAULT_PAGINATION_CLASS': 'rest_framework.pagination.CursorPagination',
  3.     'PAGE_SIZE': 100
  4. }
复制代码
    配置参数:
      - 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对象
  1. class CustomPagination(pagination.PageNumberPagination):
  2.     def get_paginated_response(self, data):
  3.         return Response({
  4.             'links': {
  5.                'next': self.get_next_link(),
  6.                'previous': self.get_previous_link()
  7.             },
  8.             'count': self.page.paginator.count,
  9.             'results': data
  10.         })
  11. # 设置自定义分页、
  12. REST_FRAMEWORK = {
  13.     'DEFAULT_PAGINATION_CLASS': 'my_project.apps.core.pagination.CustomPagination',
  14.     'PAGE_SIZE': 100
  15. }
复制代码
九  解析器

  默认的三个解析器 
    - JsonParser  Json数据解析器
    -  FormParser 和 MultiPartParser 一般同时使用
      Both request.data will be populated with a QueryDict. 官方文档的解释
  1. DEFAULTS = {
  2.     # rest_framework  settings.py
  3.     'DEFAULT_PARSER_CLASSES': (
  4.         'rest_framework.parsers.JSONParser',
  5.         'rest_framework.parsers.FormParser',
  6.         'rest_framework.parsers.MultiPartParser'
  7.     ),
  8. }
复制代码
 
十   渲染器

  默认的两个渲染器,一个是Json的,一个是用浏览器访问rest_framework自带的模板的
  1. DEFAULTS = {
  2.     # rest_framework   setting.py
  3.     'DEFAULT_RENDERER_CLASSES': (
  4.         'rest_framework.renderers.JSONRenderer',
  5.         'rest_framework.renderers.BrowsableAPIRenderer',
  6.     ),
  7. }
复制代码
 
 
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

正序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

东湖之滨

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表