drf框架相关

Posted wyf20190411-

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了drf框架相关相关的知识,希望对你有一定的参考价值。

drf框架: django-rest framework

1.接口:联系两个物质的媒介,完成信息交互
    web程序中:联系前台页面与后台数据库的媒介,已完成信息的交互;
    web接口组成:
        url:长得像放回数据的url链接
        请求参数:前台按照指定的key提供数据给后台
        响应数据:后台与数据库交互后将数据反馈给前台 
2.restful接口规范 -> 规范化书写接口
    定义:为了采用不同的后台语言,也能用同样的接口来获取到同样的数据;
    接口文档: 写接口要写 url,响应数据
        注:如果将请求参数也纳入考量范围,那就是写接口文档
        
    .url:
        1.用api关键字标识接口url     eg:api.baidu.com | www.baidu.com/api
        2.接口数据安全性决定优先选择https协议
        3.如果一个接口有多版本存在,需要在url中标识提现
           eg:    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.资源往往涉及数据的各种操作方式 --筛选,排序,限制
            eg: api.baidu.com/books/?search=系&ordering=price&limit=3
            
    .响应数据:
        1.http请求的响应会有不同的状态码,接口用来返回操作的资源数据
            status  0(操作资源成功)  1(操作资源失败)  2(操作资源成功,但没匹配结果)
            注:资源状态码不像http状态码,一般都是后台与前台约定的
        2.资源的状态码文字提示
            status  ok  子账号有误   密码有误   用户锁定        3.资源本身
            results
            注: 删除资源成功不做任何数据返回
            
        4.不能直接放回的资源(子资源,图片,视频),返回资源的链接
3.cbv生命周期源码  --基于restful规范下的cbv接口
基础接口:
    #主路由:url.py
        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组件的子路由:api/url.py
        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()),
        ]
    #模型层:model.py
        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
    #后台层:admin.py
        from django.contrib import admin
        from . import models
        admin.site.register(models.Book)

    #数据库迁移
         python manage.py makemigrations
         python manage.py migrrate
         #注册超级管理员
         python manage.py createsuperuser
    #视图层:views.py
        from django.http import JsonResponse
        from django.views import View
        from . import models
            class Book(View):
                def get(self, request, *args, **kwargs):
                    pk = kwargs.get(pk)
                    if not pk:  # 群查
                        # 操作数据库
                        book_obj_list = models.Book.objects.all()
                        # 序列化过程
                        book_list = []
                        for obj in book_obj_list:
                            dic = {}
                            dic[title] = obj.title
                            dic[price] = obj.price
                            book_list.append(dic)
                        # 响应数据
                        return JsonResponse({
                            status: 0,
                            msg: ok,
                            results: book_list
                        }, json_dumps_params={ensure_ascii: False})
                    else:  # 单查
                        book_dic = models.Book.objects.filter(pk=pk).values(title, price).first()
                        if book_dic:
                            return JsonResponse({
                                status: 0,
                                msg: ok,
                                results: book_dic
                            }, json_dumps_params={ensure_ascii: False})
                        return JsonResponse({
                            status: 2,
                            msg: 无结果,
                        }, json_dumps_params={ensure_ascii: False}
    1.获取一个
    2.获取所有
    3.增加一个
    4.删除一个
    5.整体更新一个
    6.局部更新一个
    群增|群删|整体改群改|局部改群
        def get(self, request, *args, **kwargs):
            pk = kwargs.get(pk)
            if not pk:  # 群查
                # 操作数据库
                book_obj_list = models.Book.objects.all()
                # 序列化过程
                book_list = []
                for obj in book_obj_list:
                    dic = {}
                    dic[title] = obj.title
                    dic[price] = obj.price
                    book_list.append(dic)
                # 响应数据
                return JsonResponse({
                    status: 0,
                    msg: ok,
                    results: book_list
                }, json_dumps_params={ensure_ascii: False})
            else:  # 单查
                book_dic = models.Book.objects.filter(pk=pk).values(title, price).first()
                if book_dic:
                    return JsonResponse({
                        status: 0,
                        msg: ok,
                        results: book_dic
                    }, json_dumps_params={ensure_ascii: False})
                return JsonResponse({
                    status: 2,
                    msg: 无结果,
                }, json_dumps_params={ensure_ascii: False})
                
Postman接口工具:    
postman可以完成不同方式的请求: get|post|put...
get请求,携带参数采用Params,
post请求提交数据包有三种方式:form-data | urlencoding | json
原生django对urlencoding方式数据兼容最好
    def post(self, request, *args, **kwargs):
        # 前台通过urlencoding方式提交数据
        try:
            book_obj = models.Book.objects.create(**request.POST.dict())
            if book_obj:
                return JsonResponse({
                    status: 0,
                    msg: ok,
                    results: {title: book_obj.title, price: book_obj.price}
                }, json_dumps_params={ensure_ascii: False})
        except:
            return JsonResponse({
                status: 1,
                msg: 参数有误,
            }, json_dumps_params={ensure_ascii: False})

        return JsonResponse({
            status: 2,
            msg: 新增失败,
        }, json_dumps_params={ensure_ascii: False})


DRF框架:
    安装: pip install djangorestframework
    drf框架规矩的封装风格:
        from rest_framework.views import APIView
        from rest_framework.response import Pesponse
        from rest_framework.request import Request
        from rest_framework.serializers import Serializer
        from rest_framework.settings import APISettings
        from rest_framework.filters import SearchFilter
        from rest_framework.pagination import PageNumberPagination
        from rest_framework.authentication import TokenAuthentication
        from rest_framework.permissions import IsAuthenticated
        from rest_framework.throttling import SimpleRateThrottle
        
    class Test(APIView):
        def get(self, request, *args, **kwargs):
            return Response(drf get ok)
    
    drf请求生命周期:
        1.请求走的是APVIiew 的 as_view函数
        2.在APIView的 as_view 调用父类(django原生)的as_view,还禁用了 csrf 认证
        3.在父类的 as_view中dispatch方法请求走的又是APIV接我的dispatch
        4.完成任务方法交给视图类的请求函数处理,得到请求的响应结果,返回给前台

    请求模块: request对象:
        源码入口:APIView类的dispatch方法中:
        源码分析:
            #二次封装得到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.__getattrigute__(attr)

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


    渲染模块:浏览器和Postman请求结果渲染数据的方式不一样
        源码入口:APIView类的dispatch方法中:self.response = self.finalize_response(request, response, *args, **kwargs)
        源码分析:
            #解析reponse对象数据
            self.response = self.finalize_response_response(request,response,*args,**kwargs)点进去
            #拿到运行的解析类的对象萌:
            neg = self.perform_content_negotiation(request,force=True) 点进去
            #获取解析类对象
            renderers = self.get_genderers() 点进去
            #从视图类中得到renderer_classes请求类,如何实例化一个个对象形参解析类对象列表
            return [renderer() for renderer in self.renderer_classes]
    
    重点:self.renderer_classes获取renderer_rendererd_classes的顺序
        1.自己视图类的类属性(局部配置) =>
        2.APIView类的类属性设置 =>
        3.自己配置文件的DEFAULT_RENDERER_CLASSES(全局配置) =>
        4.drf配置文件的DEFAULT_RENDERER_CLASSES
        
    全局配置:所有视图类统一处理,在项目的settings.py中    
        REST_FRAMEWORK = {
            # drf提供的渲染类
            DEFAULT_RENDERER_CLASSES: [
                rest_framework.renderers.JSONRenderer,
                rest_framework.renderers.BrowsableAPIRenderer,
            ],
        }
    局部配置:某一个或一些实体类单独处理,在views.py视图类中提供对应的类属性
        from rest_framework.renderers import JSONRenderer
        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
        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)
    


4.请求组件,解析组件,响应组件
5.序列化组件(灵魂)
6.三大认证(*****************)
    --认证,权限(权限六表),频率
7.其他组件:过滤,筛选,排序,分页,路由  
    注:难点在源码分析

 

以上是关于drf框架相关的主要内容,如果未能解决你的问题,请参考以下文章

技术博客-1 DRF框架下的图片(文件)上传

技术博客-1 DRF框架下的图片(文件)上传

DRF框架认证组件

DRF框架serializer之视图优化

DRF框架之mixins

DRF框架serializer之ModelSerializer