• Django REST framework


    Web应用模式

    在开发Web应用中,有两种应用模式:

    前后端混合开发(前后端不分离):返回的是html的内容,需要写模板

    前后端分离:只专注于写后端接口,返回json,xml格式数据

    前后端不分离

    前后端分离

    api接口

    为了在团队内部形成共识、防止个人习惯差异引起的混乱,我们需要找到一种大家都觉得很好的接口实现规范,而且这种规范能够让后端写的接口,用途一目了然,减少双方之间的合作成本。

    通过网络,规定了前后台信息交互规则的url链接,也就是前后台信息交互的媒介

    接口文档

    一旦前后端分离以后,前端根本不清楚后端在写什么,要求的参数是什么不知道,返回什么格式的数据也不知道,所以每写一个接口,就要写一个接口文档

    • 可以手动写(公司有平台,录到平台里)

    • 自动生成(coreapi,swagger)

    restful规范

    REST全称是Representational State Transfer,中文意思是表述(编者注:通常译为表征性状态转移)。
    
    RESTful是一种定义Web API接口的设计风格,尤其适用于前后端分离的应用模式中。
    
    这种风格的理念认为后端开发任务就是提供数据的,对外提供的是数据资源的访问接口,所以在定义接口时,客户端访问的URL路径就表示这种要操作的数据资源。
    
    在前后端不分离的项目中,网页所需要的数据可以直接通过模板渲染的方式传递到前端页面,并且可以很好的支持django自带的各种验证工具,比如csrfmiddleware
    
    但在前后端分离的项目中,前后端的数据通信普遍通过json字符串的形式通信,那么我们就需要有个标准去定义前后端沟通方式或者说格式
    
    restful就是来干这件事情的,它是一种面向资源的架构,规定API如何编写,通过它我们可以让api更加简洁可维护,是对于我们写程序的一些规范
    
    事实上,我们可以使用任何一个框架都可以实现符合restful规范的API接口。

    restful规范只是一种规范(10条,规定了这么做,并不是强制性的,公司可以不采用,可以结合自身需要去做适配和调整)

    1 数据的安全保障,通常使用https进行传输

    url链接一般都采用https协议进行传输

    注:采用https协议,可以提高数据交互过程中的安全性

    2 接口特征表现,域名有区分(路径中带api标识)

    https://api.example.com  # 尽量将API部署在专用域名
    https://127.0.0.0:8080/api/    # API很简单
    注:看到api字眼,就代表该请求url链接是完成前后台数据交互的

    3 多版本共存:请求地址中带版本,或者在请求头中

    在url链接中标识数据版本
    https://127.0.0.0:8080/api/v1/ # 这里的v1表示接口版本

    4 数据即是资源,均使用名词表示 (尽量不要用动词)

    https://api.example.com/v1/books/  book即是名词,不再出现动词表示操作了
    https://api.example.com/v1/get_all_books(不符合规范)

    5 通过请求方式区分不同操作

    操作资源一般都会涉及到增删改查,我们提供请求方式来标识增删改查动作
    get 请求:获取数据 post 请求:新增数据 put
    /patch 请求:patch是局部更新,put是全部更新(基本上更新都用put) delete 请求:删除

    6 在请求路径中带过滤

    通过在url上传参的形式传递搜索条件
    https://api.example.com/v1/zoos?limit=10 :指定返回记录的数量
    https://api.example.com/v1/zoos?offset=10 :指定返回记录的开始位置
    https://api.example.com/v1/zoos?page=2&per_page=100 :指定第几页,以及每页的记录数
    https://api.example.com/v1/zoos?sortby=name&order=asc :指定返回结果按照哪个属性排序,以及排序顺序
    https://api.example.com/v1/zoos?animal_type_id=1 :指定筛选条件

    7 返回中带状态码

    json数据带状态码:自己定义的,http响应中带状态码(标志当次请求成功或失败)
    - 正常响应 响应状态码2xx 200:常规请求 201:创建成功
         204:删除成功
    - 重定向响应 响应状态码3xx 301:永久重定向 302:暂时重定向 - 客户端异常 响应状态码4xx 403:请求无权限 404:请求路径不存在 405:请求方法不存在 - 服务器异常 响应状态码5xx 500:服务器异常

    8 返回数据中带错误信息

    错误处理,应返回错误信息,error当做key

    {
       error: "Invalid API key"
    }

    response['status'] = 101 response['msg'] = '验证码错误'

    9 对不同操作,返回数据符合如下规范(这只是规范)

    GET /books:返回资源对象的列表(数组)[{},{},{}]
    GET /books/1:返回单个资源对象    {}
    POST /books:返回新生成的资源对象  {新增的书}
    PUT /books/1:返回完整的资源对象   {返回修改后的}
    PATCH /books/1: 返回完整的资源对象  {返回修改后的}
    DELETE /books/1:返回一个空文档   
    ​
    {status:100,msg:查询成功,data:null}

    10 返回结果中带链接

     restful API 最好做的Hypermedia,即返回结果中提供链接,连向其它API方法,让用户不查文档,也知道下一步应该做什么。通俗理解就是数据中的子资源(图片,视频),资源链接


     

    postman的使用

    Postman是一款接口调试工具,是一款免费的可视化软件,同时支持各种操作系统平台,是测试接口的首选工具。

    模拟发送http请求,携带数据(请求地址,请求头,请求体,编码格式) 快速把接口导入导出

    1 后端写好接口要测试,后端开发要使用一个工具测试接口(postman)
    2 下载---一路下一步--装成功了
    3 会发送http请求,get,post请求即可
    4 请求地址带参数,请求体带数据,请求头加数据
    5 响应cookie,响应头,响应体

     

    Django Rest_Framework介绍和安装

    核心思想: 缩减编写api接口的代码

    Django REST framework是一个建立在Django基础之上的Web 应用开发框架,可以快速的开发REST API接口应用。在REST framework中,提供了序列化器Serialzier的定义,可以帮助我们简化序列化与反序列化的过程,不仅如此,还提供丰富的类视图、扩展类、视图集来简化视图的编写工作。REST framework还提供了认证、权限、限流、过滤、分页、接口文档等功能支持。REST framework提供了一个API 的Web可视化界面来方便查看测试接口。

    特点

    • 提供了定义序列化器Serializer的方法,可以快速根据 Django ORM 或者其它库自动序列化/反序列化;

    • 提供了丰富的类视图、Mixin扩展类,简化视图的编写;

    • 丰富的定制层级:函数视图、类视图、视图集合到自动生成 API,满足各种需要;

    • 多种身份认证和权限认证方式的支持;[jwt]

    • 内置了限流系统;

    • 直观的 API web 界面;

    • 可扩展性,插件丰富

    drf安装

    1 可以更方便的使用django写出符合resful规范的接口(不用也可以写符合规范的接口)
    2 是一个app
    3 安装 pip3 install djangorestframework
    4 https://www.django-rest-framework.org/

    drf 简单使用(csrf已经禁用掉了)

    # 路由 urls.py
    path('test/', views.Test.as_view()),
    # 视图类 views.py
    from rest_framework.views import APIView
    from rest_framework.response import Response
    class Test(APIView):
        def get(self,request):
            return Response({'name':'lqz','age':'19'})
        def post(self,request):
            return Response({'name': 'egon', 'age': '19'})
    # 注册app settings.py
    INSTALLED_APPS = [
        
        'rest_framework'
    ]
    # 在请求地址中访问
    http://127.0.0.1:8001/test/

    drf 快速使用

    在app目录中创建一个serializer.py的文件,文件名可以自定义

    
    
    
    # 1.在settings.py配置中的app注册
    ​
    INSTALLED_APPS = [
        'rest_framework'
    ]
    ​
    # 2.在模型层 models.py中写表模型
    from django.db import models
    class Book(models.Model):
        name = models.CharField(max_length=32)
        publish = models.CharField(max_length=32)
        price = models.IntegerField()
    
    ​
    # 3.在视图 views.py中写视图类
    from rest_framework.viewsets import ModelViewSet
    from app import models
    from app.serializer import  BookSerializer
    class BookView(ModelViewSet):
        serializer_class =BookSerializer
        
        
    # 4.在路由 urls.py中写路由关系
    from rest_framework.routers import SimpleRouter
    from app import views
    ​
    router = SimpleRouter()
    router.register('books', views.BookView)
    urlpatterns = [
        path('admin/', admin.site.urls),
    ]
    urlpatterns += router.urls
    ​
    ​
    # 5.在序列化器 serializer.py(需要手动创建)中写序列化类,继承ModelSerializer
    from rest_framework.serializers import ModelSerializer
    from app import models
    class BookSerializer(ModelSerializer):
        class Meta:
            model = models.Book
            fields = '__all__'# 6.启动项目,在postman中进行测试

    CBV源码分析和APIView源码分析

    cbv执行流程

        path('test/',views.TestView.as_view()),
        # path('test/',View类的as_view内部有个view闭包函数内存地址),
        '''
        1 path的第二个参数是:View类的as_view内部有个view闭包函数内存地址
        2 一旦有请求来了,匹配test路径成功
        3 执行第二个参数view函数内存地址(requset)
        4 本质执行了self.dispatch(request)
        5 通过反射去获得方法(如果是get请求,就是get方法)
         if request.method.lower() in self.http_method_names:
            handler = getattr(self, request.method.lower(), self.http_method_not_allowed)
        6 执行get方法,传入参数
        handler(request, *args, **kwargs)
        '''

    APIView的执行流程

      # path('test/',APIView类的as_view内部是用了View的as_view内的view闭包函数),
        '''
        1 path的第二个参数是:APIView类的as_view内部使用了View的as_view内的view闭包函数
        2 一旦有请求来了,匹配test路径成功
        3 执行第二个参数view函数内存地址(requset),还是执行View的as_view内的view闭包函数,但是加了个csrf_exempt装饰器
        4 所以,继承了APIView的所有接口,都没有csrf的校验了 (*****************)
        5 执行self.dispatch(request)----》APIView类的
            def dispatch(self, request, *args, **kwargs):
                # 以后所有的request对象,都是****新的request对象***,它是drf的Request类的对象
                request = self.initialize_request(request, *args, **kwargs)
                self.request = request
                try:
                    #整个drf的执行流程内的权限,频率,认证
                    self.initial(request, *args, **kwargs)
                    if request.method.lower() in self.http_method_names:
                        handler = getattr(self, request.method.lower(),
                                          self.http_method_not_allowed)
                    else:
                        handler = self.http_method_not_allowed
        
                    response = handler(request, *args, **kwargs)
        
                except Exception as exc:
                    # 全局异常
                    response = self.handle_exception(exc)
                # 响应
                self.response = self.finalize_response(request, response, *args, **kwargs)
                return self.response
    ​
        '''
        
    ### request = self.initialize_request(request, *args, **kwargs)
    ##返回的request对象是drf   Request类的request对象
    def initialize_request(self, request, *args, **kwargs):
        return Request(
            request,
            parsers=self.get_parsers(),
            authenticators=self.get_authenticators(),
            negotiator=self.get_content_negotiator(),
            parser_context=parser_context
        )
    ### *******以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了
    ​
    ​
    ​
     #####你需要记住的
        -0 所有的csrf都不校验了
        -1 request对象变成了新的request对象,drf的request对象
        -2 执行了权限,频率,认证
        -3 捕获了全局异常(统一处理异常)
        -4 处理了response对象,如果浏览器访问是一个样,postman访问又一个样
        -5 以后,在视图类中使用的request对象已经不是原来的request对象了,现在都是drf的request对象了

    Request对象分析

    1 django 原生的Request:
        django.core.handlers.wsgi.WSGIRequest
    2 drf的Request:
        rest_framework.request.Request
    
    3 drf的request对象内有原生的request
        request._request:原生的Request
    4 在视图类中使用
        request.method  拿到的就是请求方式,
        正常拿,应该request._request.method
    5 如何实现这种操作?
        -对象.属性会触发 类的__getattr__方法
        
        
    6 drf的Request类重写了__getattr__
        def __getattr__(self, attr):
            try:
                # 通过反射,取原生的request对象,取出属性或方法
                return getattr(self._request, attr)
            except AttributeError:
                return self.__getattribute__(attr)
            
            
     7 虽然视图类中request对象变成了drf的request,但是用起来,跟原来的一样,只不过它多了一些属性
        第一个:request.data   # post请求提交的数据,不论什么格式,都在request.data中
        第二个:requst.query_params # get请求提交的数据(查询参数)
        
        
    8 重点记住:
        -drf的request对象用起来跟原来一样(重写了__getattr__)
        -request.data  # post请求提交的数据,不论什么格式,都在request.data中
        -requst.query_params  # get请求提交的数据(查询参数)

    总结

    1 cbv执行流程
        -路由里写的是  类名.as_view(),
        -as_view()执行完是一个闭包函数的内存地址
        -当请求来了,路由匹配上就会调用 闭包函数(request)
        -self.dispatch(requset)
        -通过反射,去类中根据请求方式取方法,执行,把参数传入
    2 APIView的执行流程
        -以后写drf,最顶层都是APIView
        -类名.as_view()是APIView,内部调用了父类的view
        -在后加了去除csrf
        -self.dispatch(requset)是APIView的
            -包装新的request
            -执行了权限,频率,认证
            -处理了全局异常
            -处理了响应
    4 drf的Request类
        -重写了__getattr__ :新的request用起来,跟之前一模一样
        -drf的reqeust._request 是原来的request
        -request.data :post,put,patch,请求的body体中的数据,都从data中取
    从来就没有正确的选择,我们只不过是要努力奋斗,使当初的选择变得正确。
  • 相关阅读:
    oc kvc的模式:匹配搜索模式(模式匹配)、装包解包
    编程语言的多态与动态
    swift的@objc总结
    swift函数的调用约定
    PHP实现微信退款的分析与源码实现
    【MySQL】20个经典面试题,全部答对月薪10k+
    redis面试题总结
    【Redis缓存机制】1.Redis介绍和使用场景
    php四种文件加载语句
    做网站-mysql表字段设计
  • 原文地址:https://www.cnblogs.com/gfeng/p/14653671.html
Copyright © 2020-2023  润新知