zoukankan      html  css  js  c++  java
  • DRF框架简介

    一:基础简介

    (1)接口:

      (1)生活中:连接两个物体的媒介

      (2)web:连接前段后端的媒介

    (2)接口的组成

      (1)url:

      (2)请求参数:按照后端的要求 前段输入指定的key提交给后端

      (3)响应结果:后台与数据库交互数据 传递给前端

    二:restfull接口规范

    (1)作用:

      (1)根据不同的语音环境写同样的接口 后端也能获取数据

    (2)接口组成

    (1)url

    1: 用api关键字标识接口url
        api.baidu.com | www.baidu.com/api
        
    2):接口数据安全性决定优先选择https协议
    
    3: 如果一个接口有多版本存在,需要在url中标识体现
        api.baidu.com/v1/... | api.baidu.com/v2/...
        
    4):接口操作的数据源称之为 资源,在url中一般采用资源复数形式,一个接口可以概括对该资源的多种操作方式
        api.baidu.com/books | api.baidu.com/books/(pk)
        
    5: 请求方式有多种,用一个url处理如何保证不混乱 - 通过请求方式标识操作资源的方式
        /books        get            获取所有
        /books        post        增加一个(多个)
        /books/(pk)    delete        删除一个
        /books/(pk)    put            整体更新一个
        /books/(pk)    patch        局部更新一个
    
    6: 资源往往涉及数据的各种操作方式 - 筛选、排序、限制
        api.baidu.com/books/?search=西&ordering=-price&limit=3

    (2)响应数据

    1: http请求的响应会有响应状态码,接口用来返回操作的资源数据,可以拥有 操作数据结果的 状态码
        status  0(操作资源成功)  1(操作资源失败)  2(操作资源成功,但没匹配结果)
        注:资源状态码不像http状态码,一般都是后台与前台或是客户约定的
        
    2: 资源的状态码文字提示
        status  ok    '账号有误'  '密码有误'  '用户锁定'
        
    3: 资源本身
        results
        注:删除资源成功不做任何数据返回(返回空字符串)
        
    4: 不能直接放回的资源(子资源、图片、视频等资源),返回该资源的url链接

     三:基于restful规范的原生接口书写方式

    # 主路由 做路由分发
    from django.conf.urls import url, include
    from django.contrib import admin
    urlpatterns
    = [ url(r'^admin/', admin.site.urls), # 路由分发 url(r'^api/', include('api.urls')) ]
    # api子组件路由
    
    from django.conf.urls import url
    
    from . import views
    urlpatterns = [
        url(r'^books/', views.Book.as_view()),
        url(r'^books/(?P<pk>.*)/$', views.Book.as_view()),
    ]
    # 模型层
    from django.db import models
    
    class Book(models.Model):
        title = models.CharField(max_length=64)
        price = models.DecimalField(max_digits=5, decimal_places=2)
    
        class Meta:
            db_table = 'old_boy_book'  # 数据库重命名
            verbose_name = '书籍'         # 表格命名
            verbose_name_plural = verbose_name # 调用表格
    
        def __str__(self):
            return '《%s》' % self.title
    from . import models  #
    from django.views import View
    from django.http import JsonResponse
    
    
    class Book(View):
        def get(self, request, *args, **kwargs):  # get请求
            primary_key = kwargs.get('primary_key')  # 匹配前面有名分组
            if not primary_key:  # 查询所有
                book_obj_list = models.Book.objects.all()
                print(book_obj_list)  # <QuerySet [<Book: <<西游记>>>, <Book: <<红楼梦>>>]>
                book_list = []
                # 序列化开始
                for book_obj in book_obj_list:
                    back_dic = {}
                    back_dic['name'] = book_obj.name
                    back_dic['price'] = book_obj.price
                    book_list.append(back_dic)
                #    序列化结束
    
                # 返回数据给前段
                return JsonResponse({
                    'status': 0,
                    'msg': '查询成功',
                    'results': book_list,
    
                }, json_dumps_params={'ensure_ascii': False})
            else:  # 查询单个
                book_dict = models.Book.objects.filter(pk=primary_key).values('name', 'price').first()
                print(book_dict, type(book_dict))  # <QuerySet [<Book: <<西游记>>>, <Book: <<红楼梦>>>]>
                if not book_dict:  # 判断数据是否存在
                    return JsonResponse(
                        {'status': 1,
                         'msg': '该书籍不存在',
                         },
                        json_dumps_params={'ensure_ascii': False}
                    )
                return JsonResponse({
                    'status': 1,
                    'msg': '查询成功',
                    'result': book_dict
                },
                    json_dumps_params={'ensure_ascii': False}
                )
    
        def post(self, request, *args, **kwargs):  # post请求
            print(request.POST.dict())  # {'name': '神墓', 'price': '199.99'}
            recv_dict = request.POST.dict()
            book_obj = models.Book.objects.create(**recv_dict)  # 获取用户输入的值 将对象打散转换成字典形式
            if not book_obj:
                return JsonResponse({
                    'status': 1,
                    'msg': '创建异常'
                },
                    json_dumps_params={'ensure_ascii': False})
            return JsonResponse({
                'status': 0,
                'msg': '添加成功',
                'results': {'name': book_obj.name, 'price': book_obj.price}
            },
                json_dumps_params={'ensure_ascii': False})
    视图层

    PS:

      (1)postman可以完成不同方式的请求:get | post | put ...
      (2) postman发送数据包有三种方式:form-data | urlencoding | json
      (3)原生django对urlencoding方式数据兼容最好

    四:DRF框架

    # 安装
    pip3 install djangorestframework
    """
    1) 请求走的是APIView的as_view函数
    
    2) 在APIView的as_view调用父类(django原生)的as_view,还禁用了 csrf 认证
    
    3) 在父类的as_view中dispatch方法请求走的又是APIView的dispatch
    
    4) 完成任务方法交给视图类的请求函数处理,得到请求的响应结果,返回给前台
    """

    (1)请求模块 request对象

    (1)源码入口

    APIView类的dispatch方法中:request = self.initialize_request(request, *args, **kwargs)

    (2)源码分析

    """
    # 二次封装得到def的request对象
    request = self.initialize_request(request, *args, **kwargs) 点进去
    
    # 在rest_framework.request.Request实例化方法中
    self._request = request  将原生request作为新request的_request属性
    
    # 在rest_framework.request.Request的__getattr__方法中
    try:
        return getattr(self._request, attr)  # 访问属性完全兼容原生request
    except AttributeError:
        return self.__getattribute__(attr
    class Test(APIView):
        def get(self, request, *args, **kwargs):
            # url拼接的参数
            print(request._request.GET)  # 二次封装方式
            print(request.GET) # 兼容
            print(request.query_params) # 拓展
    
            return Response('drf get ok')
    
        def post(self, request, *args, **kwargs):
            # 所有请求方式携带的数据包
            print(request._request.POST)  # 二次封装方式
            print(request.POST)  # 兼容
            print(request.data)  # 拓展,兼容性最强,三种数据方式都可以
    
            print(request.query_params)
    
            return Response('drf post ok')
    视图层案例

    PS:

      (1) drf 对原生request做了二次封装,request._request就是原生request
      (2) 原生request对象的属性和方法都可以被drf的request对象直接访问(兼容)
      (3) drf请求的所有url拼接参数均被解析到query_params中,所有数据包数据都被解析到data中

    (2)渲染模块

     (1)源码入口

    APIView类的dispatch方法中:self.response = self.finalize_response(request, response, *args, **kwargs)

    (2)源码分析

    """
    # 最后解析reponse对象数据
    self.response = self.finalize_response(request, response, *args, **kwargs) 点进去
    
    # 拿到运行的解析类的对象们
    neg = self.perform_content_negotiation(request, force=True) 点进去
    
    # 获得解析类对象
    renderers = self.get_renderers() 点进去
    
    # 从视图类中得到renderer_classes请求类,如何实例化一个个对象形参解析类对象列表
    return [renderer() for renderer in self.renderer_classes]
    
    
    # 重点:self.renderer_classes获取renderer_classes的顺序
    #    自己视图类的类属性(局部配置) => 
    #    APIView类的类属性设置 => 
    #    自己配置文件的DEFAULT_RENDERER_CLASSES(全局配置) => 
    #    drf配置文件的DEFAULT_RENDERER_CLASSES
    """

    (3)全局配置:所有配置在settings文件配置

    REST_FRAMEWORK = {
        # drf提供的渲染类
        'DEFAULT_RENDERER_CLASSES': [
            'rest_framework.renderers.JSONRenderer',
            'rest_framework.renderers.BrowsableAPIRenderer',  # 此处有bug 源码问题 注意更改
        ],
    }

    (4)局部配置:某一个或一些实体类单独处理,在views.py视图类中提供对应的类属性

    class Test(APIView):
        def get(self, request, *args, **kwargs):
            return Response('drf get ok')
    
        def post(self, request, *args, **kwargs):
            return Response('drf post ok')
    
    # 在setting.py中配置REST_FRAMEWORK,完成的是全局配置,所有接口统一处理
    # 如果只有部分接口特殊化,可以完成 - 局部配置
    from rest_framework.renderers import JSONRenderer
    class Test2(APIView):
        # 局部配置
        renderer_classes = [JSONRenderer]
        def get(self, request, *args, **kwargs):
            return Response('drf get ok 2')
    
        def post(self, request, *args, **kwargs):
            return Response('drf post ok 2')
  • 相关阅读:
    xls与csv文件的区别
    青音,经典爱情语录
    win7用户账户自动登录方法汇总
    How to using Procedure found Lead Blocker
    FTS(3) BSD 库函数手册 遍历文件夹(二)
    FTS(3) BSD 库函数手册 遍历文件夹(一)
    DisplayMetrics类 获取手机显示屏的基本信息 包括尺寸、密度、字体缩放等信息
    About App Distribution 关于应用发布
    FTS(3) 遍历文件夹实例
    OpenCV 2.1.0 with Visual Studio 2008
  • 原文地址:https://www.cnblogs.com/SR-Program/p/11674255.html
Copyright © 2011-2022 走看看