码迷,mamicode.com
首页 > 其他好文 > 详细

rest_framework

时间:2018-06-29 23:32:15      阅读:178      评论:0      收藏:0      [点我收藏+]

标签:普通用户   get   获取   分页   outer   war   角色   序列   click   

1. 开发模式
        - 普通开发方式(前后端放在一起写)
        - 前后端分离

    2. 后端开发
        为前端提供URL(API/接口的开发)
        注:永远返回HttpResponse

    3. Django FBV、CBV
        FBV,function base view
            def users(request):
                user_list = [alex,oldboy]
                return HttpResponse(json.dumps((user_list)))

        CBV,class base view
            路由:
                url(r^students/, views.StudentsView.as_view()),

            视图:
                from django.views import View

                class StudentsView(View):

                    def get(self,request,*args,**kwargs):
                        return HttpResponse(GET)

                    def post(self, request, *args, **kwargs):
                        return HttpResponse(POST)

                    def put(self, request, *args, **kwargs):
                        return HttpResponse(PUT)

                    def delete(self, request, *args, **kwargs):
                        return HttpResponse(DELETE)
    4. 列表生成式

        class Foo:
            pass

        class Bar:
            pass

        v = []
        for i in [Foo,Bar]:
            obj = i()
            v.append(obj)


        v = [item() for item in [Foo,Bar]]

        v对象列表

    5. 面向对象
        - 封装
            - 对同一类方法封装到类中
                class File:
                    文件增删改查方法

                Class DB:
                    数据库的方法

            - 将数据封装到对象中
                class File:
                    def __init__(self,a1,a2):
                        self.a1 = a1
                        self.xxx = a2
                    def get:...
                    def delete:...
                    def update:...
                    def add:...

                obj1 = File(123,666)
                obj2 = File(456,999)

            PS: 扩展
                class Request(object):

                    def __init__(self,obj):
                        self.obj = obj

                    @property
                    def user(self):
                        return self.obj.authticate()

                class Auth(object):
                    def __init__(self,name,age):
                        self.name = name
                        self.age = age

                    def authticate(self):
                        return self.name


                class APIView(object):

                    def dispatch(self):
                        self.f2()

                    def f2(self):
                        a = Auth(alex,18)
                        b = Auth(oldboy,18)
                        req = Request(b)
                        print(req.user)

                obj = APIView()
                obj.dispatch()





    1. restful 规范(建议)

    2. django rest framework框架

内容详细:
    0. FBV、CBV
        CBV,基于反射实现根据请求方式不同,执行不同的方法。
        原理:
            url -> view方法 -> dispatch方法(反射执行其他:GET/POST/DELETE/PUT)

        流程:
            class StudentsView(View):
                def dispatch(self, request, *args, **kwargs):
                    print(before)
                    ret = super(StudentsView,self).dispatch(request, *args, **kwargs)
                    print(after)
                    return ret

                def get(self,request,*args,**kwargs):
                    return HttpResponse(GET)

                def post(self, request, *args, **kwargs):
                    return HttpResponse(POST)

                def put(self, request, *args, **kwargs):
                    return HttpResponse(PUT)

                def delete(self, request, *args, **kwargs):
                    return HttpResponse(DELETE)

        继承(多个类共用的功能,为了避免重复编写):
            from django.views import View


            class MyBaseView(object):
                def dispatch(self, request, *args, **kwargs):
                    print(before)
                    ret = super(MyBaseView,self).dispatch(request, *args, **kwargs)
                    print(after)
                    return ret

            class StudentsView(MyBaseView,View):

                def get(self,request,*args,**kwargs):
                    print(get方法)
                    return HttpResponse(GET)

                def post(self, request, *args, **kwargs):
                    return HttpResponse(POST)

                def put(self, request, *args, **kwargs):
                    return HttpResponse(PUT)

                def delete(self, request, *args, **kwargs):
                    return HttpResponse(DELETE)
           ############################################################
            class TeachersView(MyBaseView,View):

                def get(self,request,*args,**kwargs):
                    return HttpResponse(GET)

                def post(self, request, *args, **kwargs):
                    return HttpResponse(POST)

                def put(self, request, *args, **kwargs):
                    return HttpResponse(PUT)

                def delete(self, request, *args, **kwargs):
                    return HttpResponse(DELETE)

        面试题:
            1. django中间件
                - process_request
                - process_view
                - process_response
                - process_exception
                - process_render_template
            2. 使用中间件做过什么?
                - 权限
                - 用户登录验证
                - django的csrf是如何实现?
                    process_view方法
                        - 检查视图是否被 @csrf_exempt (免除csrf认证)
                        - 去请求体或cookie中获取token
            3.
                情况一:
                    MIDDLEWARE = [
                        django.middleware.security.SecurityMiddleware,
                        django.contrib.sessions.middleware.SessionMiddleware,
                        django.middleware.common.CommonMiddleware,
                        django.middleware.csrf.CsrfViewMiddleware, # 全站使用csrf认证
                        django.contrib.auth.middleware.AuthenticationMiddleware,
                        django.contrib.messages.middleware.MessageMiddleware,
                        django.middleware.clickjacking.XFrameOptionsMiddleware,
                    ]


                    from django.views.decorators.csrf import csrf_exempt
                    @csrf_exempt # 该函数无需csrf认证
                    def users(request):
                        user_list = [alex,oldboy]
                        return HttpResponse(json.dumps((user_list)))

                情况二:
                    MIDDLEWARE = [
                        django.middleware.security.SecurityMiddleware,
                        django.contrib.sessions.middleware.SessionMiddleware,
                        django.middleware.common.CommonMiddleware,
                        #‘django.middleware.csrf.CsrfViewMiddleware‘, # 全站不使用csrf认证
                        django.contrib.auth.middleware.AuthenticationMiddleware,
                        django.contrib.messages.middleware.MessageMiddleware,
                        django.middleware.clickjacking.XFrameOptionsMiddleware,
                    ]


                    from django.views.decorators.csrf import csrf_exempt
                    @csrf_protect # 该函数需csrf认证
                    def users(request):
                        user_list = [alex,oldboy]
                        return HttpResponse(json.dumps((user_list)))


        CBV小知识,csrf时需要使用
            - @method_decorator(csrf_exempt)
            - 在dispatch方法中(单独方法无效)

            方式一:
                from django.views.decorators.csrf import csrf_exempt,csrf_protect
                from django.utils.decorators import method_decorator
                class StudentsView(View):

                    @method_decorator(csrf_exempt)
                    def dispatch(self, request, *args, **kwargs):
                        return super(StudentsView,self).dispatch(request, *args, **kwargs)

                    def get(self,request,*args,**kwargs):
                        print(get方法)
                        return HttpResponse(GET)

                    def post(self, request, *args, **kwargs):
                        return HttpResponse(POST)

                    def put(self, request, *args, **kwargs):
                        return HttpResponse(PUT)

                    def delete(self, request, *args, **kwargs):
                        return HttpResponse(DELETE)
            方式二:
                from django.views.decorators.csrf import csrf_exempt,csrf_protect
                from django.utils.decorators import method_decorator

                @method_decorator(csrf_exempt,name=dispatch)
                class StudentsView(View):

                    def get(self,request,*args,**kwargs):
                        print(get方法)
                        return HttpResponse(GET)

                    def post(self, request, *args, **kwargs):
                        return HttpResponse(POST)

                    def put(self, request, *args, **kwargs):
                        return HttpResponse(PUT)

                    def delete(self, request, *args, **kwargs):
                        return HttpResponse(DELETE)

        总结:
            - 本质,基于反射来实现
            - 流程:路由,view,dispatch(反射)
            - 取消csrf认证(装饰器要加到dispatch方法上且method_decorator装饰)

            扩展:
                - csrf
                    - 基于中间件的process_view方法
                    - 装饰器给单独函数进行设置(认证或无需认证)


    1. restful 规范(建议)
        a. 接口开发

            urlpatterns = [
                # url(r‘^admin/‘, admin.site.urls),
                url(r^get_order/, views.get_order),
                url(r^add_order/, views.add_order),
                url(r^del_order/, views.del_order),
                url(r^update_order/, views.update_order),
            ]


            def get_order(request):
                return HttpResponse(‘‘)


            def add_order(request):
                return HttpResponse(‘‘)


            def del_order(request):
                return HttpResponse(‘‘)


            def update_order(request):
                return HttpResponse(‘‘)

        b. restful 规范(建议)

            1. 根据method不同做不同的操作,示例:

                基于FBV:
                    urlpatterns = [
                        url(r^order/, views.order),
                    ]

                    def order(request):
                        if request.method == GET:
                            return HttpResponse(获取订单)
                        elif request.method == POST:
                            return HttpResponse(创建订单)
                        elif request.method == PUT:
                            return HttpResponse(更新订单)
                        elif request.method == DELETE:
                            return HttpResponse(删除订单)
                基于CBV:
                    urlpatterns = [
                        url(r^order/, views.OrderView.as_view()),
                    ]

                    class OrderView(View):
                        def get(self,request,*args,**kwargs):
                            return HttpResponse(获取订单)

                        def post(self,request,*args,**kwargs):
                            return HttpResponse(创建订单)

                        def put(self,request,*args,**kwargs):
                            return HttpResponse(更新订单)

                        def delete(self,request,*args,**kwargs):
                            return HttpResponse(删除订单)


        c. 谈谈自己对restful api 规范的认识

            10个规则


        注意:推荐使用CBV



    2. django rest framework框架
        pip3 install djangorestframework

        a. 认证
            - 仅使用:
                    from django.views import View
                    from rest_framework.views import APIView
                    from rest_framework.authentication import BasicAuthentication
                    from rest_framework import exceptions
                    from rest_framework.request import Request

                    class MyAuthentication(object):
                        def authenticate(self,request):
                            token = request._request.GET.get(token)
                            # 获取用户名和密码,去数据校验
                            if not token:
                                raise exceptions.AuthenticationFailed(用户认证失败)
                            return ("alex",None)

                        def authenticate_header(self,val):
                            pass

                    class DogView(APIView):
                        authentication_classes = [MyAuthentication,]

                        def get(self,request,*args,**kwargs):
                            print(request)
                            print(request.user)
                            ret  = {
                                code:1000,
                                msg:xxx
                            }
                            return HttpResponse(json.dumps(ret),status=201)

                        def post(self,request,*args,**kwargs):
                            return HttpResponse(创建Dog)

                        def put(self,request,*args,**kwargs):
                            return HttpResponse(更新Dog)

                        def delete(self,request,*args,**kwargs):
                            return HttpResponse(删除Dog)

            - 源码流程:
                dispatch...
***********************************************************************************

内容:
    1. 认证
    2. 权限
    3. 节流(访问频率控制)
    4. 版本

内容:
    1. 认证
        a. 问题1:有些API需要用户登录成功之后,才能访问;有些无需登录就能访问。
        b. 基本使用认证组件
            解决:
                a. 创建两张表
                b. 用户登录(返回token并保存到数据库)
        c. 认证流程原理
            - 见图示

        d. 再看一遍源码
            1. 局部视图使用&全局使用
            2. 匿名是request.user = None

        e. 内置认证类
            1. 认证类,必须继承:from rest_framework.authentication import BaseAuthentication
            2. 其他认证类:BasicAuthentication

        梳理:
            1. 使用
                - 创建类:继承BaseAuthentication; 实现:authenticate方法
                - 返回值:
                    - None,我不管了,下一认证来执行。
                    - raise exceptions.AuthenticationFailed(用户认证失败) # from rest_framework import exceptions
                    - (元素1,元素2)  # 元素1赋值给request.user; 元素2赋值给request.auth

                - 局部使用
                    from rest_framework.authentication import BaseAuthentication,BasicAuthentication
                    class UserInfoView(APIView):
                        """
                        订单相关业务
                        """
                        authentication_classes = [BasicAuthentication,]
                        def get(self,request,*args,**kwargs):
                            print(request.user)
                            return HttpResponse(用户信息)
                - 全局使用:
                    REST_FRAMEWORK = {
                        # 全局使用的认证类
                        "DEFAULT_AUTHENTICATION_CLASSES":[api.utils.auth.FirstAuthtication,api.utils.auth.Authtication, ],
                        # "UNAUTHENTICATED_USER":lambda :"匿名用户"
                        "UNAUTHENTICATED_USER":None, # 匿名,request.user = None
                        "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None
                    }
            2. 源码流程
                - dispatch
                    - 封装request
                        - 获取定义的认证类(全局/局部),通过列表生成时创建对象。
                    - initial
                        - perform_authentication
                            request.user(内部循环....)


    2. 权限
        问题:不用视图不用权限可以访问

        基本使用:

            class MyPermission(object):

                def has_permission(self,request,view):
                    if request.user.user_type != 3:
                        return False
                    return True


                class OrderView(APIView):
                    """
                    订单相关业务(只有SVIP用户有权限)
                    """
                    permission_classes = [MyPermission,]

                    def get(self,request,*args,**kwargs):
                        # request.user
                        # request.auth
                        self.dispatch
                        ret = {code:1000,msg:None,data:None}
                        try:
                            ret[data] = ORDER_DICT
                        except Exception as e:
                            pass
                        return JsonResponse(ret)

        源码流程:
            - ...

        梳理:
            1. 使用
                - 类,必须继承:BasePermission,必须实现:has_permission方法
                    from rest_framework.permissions import BasePermission

                    class SVIPPermission(BasePermission):
                        message = "必须是SVIP才能访问"
                        def has_permission(self,request,view):
                            if request.user.user_type != 3:
                                return False
                            return True
                - 返回值:
                    - True, 有权访问
                    - False,无权访问
                - 局部
                    class UserInfoView(APIView):
                        """
                        订单相关业务(普通用户、VIP)
                        """
                        permission_classes = [MyPermission1, ]

                        def get(self,request,*args,**kwargs):
                            return HttpResponse(用户信息)

                - 全局
                    REST_FRAMEWORK = {
                        "DEFAULT_PERMISSION_CLASSES":[api.utils.permission.SVIPPermission]
                    }

            2. 源码流程


    3. 访问频率控制(节流)
        问题:控制访问频率
            import time
            VISIT_RECORD = {}

            class VisitThrottle(object):
                """60s内只能访问3次"""

                def __init__(self):
                    self.history = None

                def allow_request(self,request,view):
                    # 1. 获取用户IP
                    remote_addr = request.META.get(REMOTE_ADDR)
                    ctime = time.time()
                    if remote_addr not in VISIT_RECORD:
                        VISIT_RECORD[remote_addr] = [ctime,]
                        return True
                    history = VISIT_RECORD.get(remote_addr)
                    self.history = history

                    while history and history[-1] < ctime - 60:
                        history.pop()

                    if len(history) < 3:
                        history.insert(0,ctime)
                        return True

                    # return True    # 表示可以继续访问
                    # return False # 表示访问频率太高,被限制

                def wait(self):
                    """
                    还需要等多少秒才能访问
                    :return:
                    """
                    ctime = time.time()
                    return 60 - (ctime - self.history[-1])

            class AuthView(APIView):
                """
                用于用户登录认证
                """
                authentication_classes = []
                permission_classes = []
                throttle_classes = [VisitThrottle,]

                def post(self,request,*args,**kwargs):


                    ret = {code:1000,msg:None}
                    try:
                        user = request._request.POST.get(username)
                        pwd = request._request.POST.get(password)
                        obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
                        if not obj:
                            ret[code] = 1001
                            ret[msg] = "用户名或密码错误"
                        # 为登录用户创建token
                        token = md5(user)
                        # 存在就更新,不存在就创建
                        models.UserToken.objects.update_or_create(user=obj,defaults={token:token})
                        ret[token] = token
                    except Exception as e:
                        ret[code] = 1002
                        ret[msg] = 请求异常

                    return JsonResponse(ret)

        内置控制频率类:
            from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
            class VisitThrottle(SimpleRateThrottle):
                scope = "Luffy"

                def get_cache_key(self, request, view):
                    return self.get_ident(request)


            class UserThrottle(SimpleRateThrottle):
                scope = "LuffyUser"

                def get_cache_key(self, request, view):
                    return request.user.username


            REST_FRAMEWORK = {
                # 全局使用的认证类
                "DEFAULT_AUTHENTICATION_CLASSES":[api.utils.auth.FirstAuthtication,api.utils.auth.Authtication, ],
                # "DEFAULT_AUTHENTICATION_CLASSES":[‘api.utils.auth.FirstAuthtication‘, ],
                # "UNAUTHENTICATED_USER":lambda :"匿名用户"
                "UNAUTHENTICATED_USER":None, # 匿名,request.user = None
                "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None
                "DEFAULT_PERMISSION_CLASSES":[api.utils.permission.SVIPPermission],
                "DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"],
                "DEFAULT_THROTTLE_RATES":{
                    "Luffy":3/m,
                    "LuffyUser":10/m,
                }
            }


        梳理:
            a. 基本使用
                - 类, 继承:BaseThrottle,实现:allow_request、wait
                - 类, 继承:SimpleRateThrottle,实现:get_cache_key、scope = "Luffy"(配置文件中的key)

            b. 局部
                class AuthView(APIView):
                    """
                    用于用户登录认证
                    """
                    authentication_classes = []
                    permission_classes = []
                    throttle_classes = [VisitThrottle,] # *******************

                    def post(self,request,*args,**kwargs):

                        ret = {code:1000,msg:None}
                        try:
                            user = request._request.POST.get(username)
                            pwd = request._request.POST.get(password)
                            obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
                            if not obj:
                                ret[code] = 1001
                                ret[msg] = "用户名或密码错误"
                            # 为登录用户创建token
                            token = md5(user)
                            # 存在就更新,不存在就创建
                            models.UserToken.objects.update_or_create(user=obj,defaults={token:token})
                            ret[token] = token
                        except Exception as e:
                            ret[code] = 1002
                            ret[msg] = 请求异常

                        return JsonResponse(ret)

            c. 全局
                REST_FRAMEWORK = {
                    # 全局使用的认证类
                    "DEFAULT_AUTHENTICATION_CLASSES":[api.utils.auth.FirstAuthtication,api.utils.auth.Authtication, ],
                    # "DEFAULT_AUTHENTICATION_CLASSES":[‘api.utils.auth.FirstAuthtication‘, ],
                    # "UNAUTHENTICATED_USER":lambda :"匿名用户"
                    "UNAUTHENTICATED_USER":None, # 匿名,request.user = None
                    "UNAUTHENTICATED_TOKEN":None,# 匿名,request.auth = None
                    "DEFAULT_PERMISSION_CLASSES":[api.utils.permission.SVIPPermission],

                    "DEFAULT_THROTTLE_CLASSES":["api.utils.throttle.UserThrottle"],
                    "DEFAULT_THROTTLE_RATES":{
                        "Luffy":3/m,
                        "LuffyUser":10/m,
                    }
                }

    内容:
        1. 中间件

        2. csrf原理

        3. rest 10规范

        4. 面向对象

        5. django请求声明周期

        6. django请求声明周期(包含rest framework框架)
           PS: dispatch

        7. rest framework 认证流程(封装Request.user)

        8. rest framework 权限流程

        9. rest framework 节流流程

    代码:
        认证Demo,
        权限Demo(用户类型不同,权限不同)
        节流Demo(匿名,登录用)

        三组件组合

*********************************************************************************2. Django声明周期
        a. wsgi
            wsgi,是协议。
            wsgiref,是实现了wsgi协议的一个模块。模块本质:一个socket服务端。(Django)
            werkzeug ,是实现了wsgi协议的一个模块。模块本质:一个socket服务端(Flask框架)
            tornado ,是实现了wsgi协议的一个模块。模块本质:一个socket服务端(Flask框架)
            uwsgi,是实现了wsgi协议的一个模块。模块本质:一个socket服务端。


    3. Django生命周期(rest framework)


    4. 中间件&装饰器
        - 适用于所有请求批量做操作
            场景:
                - 基于角色的权限控制
                - 用户认证
                - csrf,(说原理)
                - session(说原理)
                - 黑名单
                - 日志记录
    5. rest 框架原理
        a. 认证流程
        b. 权限
        c. 节流


内容概要:
    1. 版本      *
    2. 解析器 *
    3. 序列化 ****
        - 请求数据进行校验
        - QuerySet进行序列化
    4. 分页   **
    5. 路由   **
    6. 视图   **
    7. 渲染器 *


内容详细:
    1. 版本
        a. URL中通过GET传参()
            自定义:
                http://127.0.0.1:8000/api/users/?version=v2

                class ParamVersion(object):
                    def determine_version(self, request, *args, **kwargs):
                        version = request.query_params.get(version)
                        return version

                class UsersView(APIView):

                    versioning_class = ParamVersion
                    def get(self,request,*args,**kwargs):
                        #version = request._request.GET.get(‘version‘)
                        #print(version)
                        # version = request.query_params.get(‘version‘)
                        # print(version)

                        print(request.version)

                        return HttpResponse(用户列表)


        b. 在URL中传参(推荐使用)

            urlpatterns = [
                # url(r‘^admin/‘, admin.site.urls),
                url(r^(?P<version>[v1|v2]+)/users/$, views.UsersView.as_view()),
            ]


            REST_FRAMEWORK = {
                "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
                "DEFAULT_VERSION":v1,
                "ALLOWED_VERSIONS":[v1,v2],
                "VERSION_PARAM":version,
            }

            class UsersView(APIView):

                def get(self,request,*args,**kwargs):
                    print(request.version)
                    return HttpResponse(用户列表)

        总结:
            使用:
                配置文件:
                    REST_FRAMEWORK = {
                        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
                        "DEFAULT_VERSION":v1,
                        "ALLOWED_VERSIONS":[v1,v2],
                        "VERSION_PARAM":version,
                    }
                路由系统:

                    urlpatterns = [
                        # url(r‘^admin/‘, admin.site.urls),
                        url(r^api/, include(api.urls)),
                    ]

                    urlpatterns = [
                        # url(r‘^admin/‘, admin.site.urls),
                        url(r^(?P<version>[v1|v2]+)/users/$, views.UsersView.as_view(),name=uuu),
                    ]


                视图:

                    class UsersView(APIView):

                    def get(self,request,*args,**kwargs):

                        # 1. 获取版本
                        print(request.version)

                        # 2. 获取处理版本的对象
                        print(request.versioning_scheme)

                        # 3. 反向生成URL(rest framework)
                        u1 = request.versioning_scheme.reverse(viewname=uuu,request=request)
                        print(u1)

                        # 4. 反向生成URL
                        u2 = reverse(viewname=uuu,kwargs={version:2})
                        print(u2)

                        return HttpResponse(用户列表)

    2. 解析器
        前戏:django:request.POST/ request.body
            1. 请求头要求:
                Content-Type: application/x-www-form-urlencoded
                PS: 如果请求头中的 Content-Type: application/x-www-form-urlencoded,request.POST中才有值(去request.body中解析数据)。
            2. 数据格式要求:
                  name=alex&age=18&gender=男

            如:
                a. form表单提交
                    <form method...>
                        input...

                    </form>

                b. ajax提交
                    $.ajax({
                        url:...
                        type:POST,
                        data:{name:alex,age=18} # 内部转化 name=alex&age=18&gender=男
                    })

                    情况一:
                        $.ajax({
                            url:...
                            type:POST,
                            headers:{Content-Type:"application/json"}
                            data:{name:alex,age=18} # 内部转化 name=alex&age=18&gender=男
                        })
                        # body有值;POST无
                    情况二:
                        $.ajax({
                            url:...
                            type:POST,
                            headers:{Content-Type:"application/json"}
                            data:JSON.stringfy({name:alex,age=18}) # {name:alex,age:18...}
                        })
                        # body有值;POST无
                        # json.loads(request.body)

        rest_framework 解析器,对请求体数据进行解析

        总结:
            使用:
                配置:
                    REST_FRAMEWORK = {
                        "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
                        "DEFAULT_VERSION":v1,
                        "ALLOWED_VERSIONS":[v1,v2],
                        "VERSION_PARAM":version,

                        "DEFAULT_PARSER_CLASSES":[rest_framework.parsers.JSONParser,rest_framework.parsers.FormParser]
                    }

                使用:
                    class ParserView(APIView):
                        # parser_classes = [JSONParser,FormParser,]
                        """
                        JSONParser:表示只能解析content-type:application/json头
                        JSONParser:表示只能解析content-type:application/x-www-form-urlencoded头
                        """

                        def post(self,request,*args,**kwargs):
                            """
                            允许用户发送JSON格式数据
                                a. content-type: application/json
                                b. {‘name‘:‘alex‘,age:18}
                            :param request:
                            :param args:
                            :param kwargs:
                            :return:
                            """
                            """
                            1. 获取用户请求
                            2. 获取用户请求体
                            3. 根据用户请求头 和 parser_classes = [JSONParser,FormParser,] 中支持的请求头进行比较
                            4. JSONParser对象去请求体
                            5. request.data
                            """
                            print(request.data)


                            return HttpResponse(ParserView)


            源码流程 & 本质:
                a. 本质
                    请求头 :...
                    状态码: ...
                    请求方法:...
                b. 源码流程
                    - dispatch: request封装
                    - request.data



    3. 序列化

        序列化:
            部分总结:
                1. 写类
                    class RolesSerializer(serializers.Serializer):
                        id = serializers.IntegerField()
                        title = serializers.CharField()

                    class UserInfoSerializer(serializers.ModelSerializer):
                        class Meta:
                            model = models.UserInfo
                            # fields = "__all__"
                            fields = [id,username,password,]

                2. 字段
                    a. title = serializers.CharField(source="xxx.xxx.xx.xx")
                    b. title = serializers.SerializerMethodField()
                       class UserInfoSerializer(serializers.ModelSerializer):
                            rls = serializers.SerializerMethodField()  # 自定义显示

                            class Meta:
                                model = models.UserInfo
                                fields = [id,username,password,rls,]

                            # 自定义方法
                            def get_rls(self, row):
                                role_obj_list = row.roles.all()

                                ret = []
                                for item in role_obj_list:
                                    ret.append({id:item.id,title:item.title})
                                return ret
                    c. 自定义类

                3. 自动序列化连表
                    class UserInfoSerializer(serializers.ModelSerializer):
                    class Meta:
                        model = models.UserInfo
                        # fields = "__all__"
                        fields = [id,username,password,group,roles]
                        depth = 1 # 0 ~ 10

                4. 生成链接
                    class UserInfoSerializer(serializers.ModelSerializer):
                        group = serializers.HyperlinkedIdentityField(view_name=gp,lookup_field=group_id,lookup_url_kwarg=xxx)
                        class Meta:
                            model = models.UserInfo
                            # fields = "__all__"
                            fields = [id,username,password,group,roles]
                            depth = 0 # 0 ~ 10

                    class UserInfoView(APIView):
                        def get(self,request,*args,**kwargs):

                            users = models.UserInfo.objects.all()

                            ser = UserInfoSerializer(instance=users,many=True,context={request: request})
                            ret = json.dumps(ser.data, ensure_ascii=False)
                            return HttpResponse(ret)

            源码:
                对象, Serializer类处理;
                QuerySet,ListSerializer类处理;
                # ser.data

        请求数据校验:

                class XXValidator(object):
                    def __init__(self, base):
                        self.base = base

                    def __call__(self, value):
                        if not value.startswith(self.base):
                            message = 标题必须以 %s 为开头。 % self.base
                            raise serializers.ValidationError(message)

                    def set_context(self, serializer_field):
                        """
                        This hook is called by the serializer instance,
                        prior to the validation call being made.
                        """
                        # 执行验证之前调用,serializer_fields是当前字段对象
                        pass

                class UserGroupSerializer(serializers.Serializer):
                    title = serializers.CharField(error_messages={required:标题不能为空},validators=[XXValidator(老男人),])


                class UserGroupView(APIView):

                    def post(self,request,*args,**kwargs):

                        ser = UserGroupSerializer(data=request.data)
                        if ser.is_valid():
                            print(ser.validated_data[title])
                        else:
                            print(ser.errors)

                        return HttpResponse(提交数据)


            问: 自定义验证规则时,需要钩子函数?请问钩子函数如何写?
********************************************************************************
内容:
    0. 序列化源码

    1. 分页
        a. 分页,看第n页,每页显示n条数据;
            from rest_framework.pagination import PageNumberPagination

            class MyPageNumberPagination(PageNumberPagination):

                page_size = 2
                page_size_query_param = size
                max_page_size = 5
                page_query_param = page

            class Pager1View(APIView):

                def get(self,request,*args,**kwargs):

                    # 获取所有数据
                    roles = models.Role.objects.all()

                    # 创建分页对象
                    # pg = MyPageNumberPagination()
                    pg = PageNumberPagination()

                    # 在数据库中获取分页的数据
                    pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

                    # 对数据进行序列化
                    ser = PagerSerialiser(instance=pager_roles, many=True)

                    return Response(ser.data)
                    # return pg.get_paginated_response(ser.data)


        b. 分页,在n个位置,向后查看n条数据;

                from api.utils.serializsers.pager import PagerSerialiser
                from rest_framework.response import Response
                from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination


                class MyLimitOffsetPagination(LimitOffsetPagination):
                    default_limit = 2
                    limit_query_param = limit
                    offset_query_param = offset
                    max_limit = 5


                class Pager1View(APIView):

                    def get(self,request,*args,**kwargs):

                        # 获取所有数据
                        roles = models.Role.objects.all()

                        # 创建分页对象
                        # pg = MyLimitOffsetPagination()
                        pg = LimitOffsetPagination()

                        # 在数据库中获取分页的数据
                        pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

                        # 对数据进行序列化
                        ser = PagerSerialiser(instance=pager_roles, many=True)

                        return Response(ser.data)
                        # return pg.get_paginated_response(ser.data)



        c. 加密分页,上一页和下一页。

            from api.utils.serializsers.pager import PagerSerialiser
            from rest_framework.response import Response
            from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

            class MyCursorPagination(CursorPagination):
                cursor_query_param = cursor
                page_size = 2
                ordering = id
                page_size_query_param = None
                max_page_size = None

            class Pager1View(APIView):

                def get(self,request,*args,**kwargs):

                    # 获取所有数据
                    roles = models.Role.objects.all()

                    # 创建分页对象
                    # pg = CursorPagination()
                    pg = MyCursorPagination()

                    # 在数据库中获取分页的数据
                    pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

                    # 对数据进行序列化
                    ser = PagerSerialiser(instance=pager_roles, many=True)

                    # return Response(ser.data)
                    return pg.get_paginated_response(ser.data)
        总结:
            1. 数据量大的话,如何做分页?
                - 数据库性能相关?
    2. 视图
        a. 过去
            class Pager1View(View):
                pass

        b. 现在
            class Pager1View(APIView): # View
                pass

        c. 无用

            from api.utils.serializsers.pager import PagerSerialiser
            from rest_framework.generics import GenericAPIView

            class View1View(GenericAPIView): # APIView
                queryset = models.Role.objects.all()
                serializer_class = PagerSerialiser
                pagination_class = PageNumberPagination
                def get(self,request,*args,**kwargs):
                    # 获取数据
                    roles = self.get_queryset() # models.Role.objects.all()

                    # [1, 1000,]     [1,10]
                    pager_roles = self.paginate_queryset(roles)

                    # 序列化
                    ser = self.get_serializer(instance=pager_roles,many=True)

                    return Response(ser.data)

        d. GenericViewSet(ViewSetMixin, generics.GenericAPIView):

            路由:
                url(r^(?P<version>[v1|v2]+)/v1/$, views.View1View.as_view({get: list})),

            视图:
                from api.utils.serializsers.pager import PagerSerialiser
                from rest_framework.viewsets import GenericViewSet

                class View1View(GenericViewSet):
                    queryset = models.Role.objects.all()
                    serializer_class = PagerSerialiser
                    pagination_class = PageNumberPagination

                    def list(self, request, *args, **kwargs):
                        # 获取数据
                        roles = self.get_queryset()  # models.Role.objects.all()

                        # [1, 1000,]     [1,10]
                        pager_roles = self.paginate_queryset(roles)

                        # 序列化
                        ser = self.get_serializer(instance=pager_roles, many=True)

                        return Response(ser.data)

        e.
            路由系统:
                url(r^(?P<version>[v1|v2]+)/v1/$, views.View1View.as_view({get: list,post:create})),
                url(r^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$, views.View1View.as_view({get: retrieve,delete:destroy,put:update,patch:partial_update})),

            视图:
                from api.utils.serializsers.pager import PagerSerialiser
                from rest_framework.viewsets import GenericViewSet,ModelViewSet
                from rest_framework.mixins import ListModelMixin,CreateModelMixin

                class View1View(ModelViewSet):
                    queryset = models.Role.objects.all()
                    serializer_class = PagerSerialiser
                    pagination_class = PageNumberPagination

                PS: class View1View(CreateModelMixin,GenericViewSet):
        总结:
            a. 增删改查 ModelViewSet
            b. 增删     CreateModelMixin,DestroyModelMixin  GenericViewSet
            c. 复杂逻辑  GenericViewSet 或 APIView

            PS: 还债:
                GenericAPIView.get_object
                    check_object_permissions
                        has_object_permission

    3. 路由
        a.
            url(r^(?P<version>[v1|v2]+)/parser/$, views.ParserView.as_view()),

        b.
            url(r^(?P<version>[v1|v2]+)/v1/$, views.View1View.as_view({get: list,post:create})),

        c.
            # http://127.0.0.1:8000/api/v1/v1/?format=json
            url(r^(?P<version>[v1|v2]+)/v1/$, views.View1View.as_view({get: list,post:create})),
            # http://127.0.0.1:8000/api/v1/v1.json
            url(r^(?P<version>[v1|v2]+)/v1\.(?P<format>\w+)$, views.View1View.as_view({get: list,post:create})),

            url(r^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$, views.View1View.as_view({get: retrieve,delete:destroy,put:update,patch:partial_update})),
            url(r^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)\.(?P<format>\w+)$, views.View1View.as_view({get: retrieve,delete:destroy,put:update,patch:partial_update})),
        d.
            from api import views
            from rest_framework import routers


            router = routers.DefaultRouter()
            router.register(rxxxxx, views.View1View)
            router.register(rrt, views.View1View)

            urlpatterns = [
                url(r^(?P<version>[v1|v2]+)/, include(router.urls)),
            ]

    4. 渲染
        from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer

        class TestView(APIView):
            # renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
            def get(self, request, *args, **kwargs):
                # 获取所有数据
                roles = models.Role.objects.all()

                # 创建分页对象
                # pg = CursorPagination()
                pg = MyCursorPagination()

                # 在数据库中获取分页的数据
                pager_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)

                # 对数据进行序列化
                ser = PagerSerialiser(instance=pager_roles, many=True)

                return Response(ser.data)


        REST_FRAMEWORK = {
            "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
            "DEFAULT_VERSION":v1,
            "ALLOWED_VERSIONS":[v1,v2],
            "VERSION_PARAM":version,
            "DEFAULT_PARSER_CLASSES":[rest_framework.parsers.JSONParser,rest_framework.parsers.FormParser],
            "PAGE_SIZE":2,

            "DEFAULT_RENDERER_CLASSES":[
                rest_framework.renderers.JSONRenderer,
                rest_framework.renderers.BrowsableAPIRenderer,
            ]
        }

    5. django组件:contenttype**********************************************************************************
内容:
    0. 序列化源码

    1. 分页
        a. 分页,看第n页,每页显示n条数据;
            from rest_framework.pagination import PageNumberPagination

            class MyPageNumberPagination(PageNumberPagination):

                page_size = 2
                page_size_query_param = size
                max_page_size = 5
                page_query_param = page

            class Pager1View(APIView):

                def get(self,request,*args,**kwargs):

                    # 获取所有数据
                    roles = models.Role.objects.all()

                    # 创建分页对象
                    # pg = MyPageNumberPagination()
                    pg = PageNumberPagination()

                    # 在数据库中获取分页的数据
                    pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

                    # 对数据进行序列化
                    ser = PagerSerialiser(instance=pager_roles, many=True)

                    return Response(ser.data)
                    # return pg.get_paginated_response(ser.data)


        b. 分页,在n个位置,向后查看n条数据;

                from api.utils.serializsers.pager import PagerSerialiser
                from rest_framework.response import Response
                from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination


                class MyLimitOffsetPagination(LimitOffsetPagination):
                    default_limit = 2
                    limit_query_param = limit
                    offset_query_param = offset
                    max_limit = 5


                class Pager1View(APIView):

                    def get(self,request,*args,**kwargs):

                        # 获取所有数据
                        roles = models.Role.objects.all()

                        # 创建分页对象
                        # pg = MyLimitOffsetPagination()
                        pg = LimitOffsetPagination()

                        # 在数据库中获取分页的数据
                        pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

                        # 对数据进行序列化
                        ser = PagerSerialiser(instance=pager_roles, many=True)

                        return Response(ser.data)
                        # return pg.get_paginated_response(ser.data)



        c. 加密分页,上一页和下一页。

            from api.utils.serializsers.pager import PagerSerialiser
            from rest_framework.response import Response
            from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination

            class MyCursorPagination(CursorPagination):
                cursor_query_param = cursor
                page_size = 2
                ordering = id
                page_size_query_param = None
                max_page_size = None

            class Pager1View(APIView):

                def get(self,request,*args,**kwargs):

                    # 获取所有数据
                    roles = models.Role.objects.all()

                    # 创建分页对象
                    # pg = CursorPagination()
                    pg = MyCursorPagination()

                    # 在数据库中获取分页的数据
                    pager_roles = pg.paginate_queryset(queryset=roles,request=request,view=self)

                    # 对数据进行序列化
                    ser = PagerSerialiser(instance=pager_roles, many=True)

                    # return Response(ser.data)
                    return pg.get_paginated_response(ser.data)
        总结:
            1. 数据量大的话,如何做分页?
                - 数据库性能相关?
    2. 视图
        a. 过去
            class Pager1View(View):
                pass

        b. 现在
            class Pager1View(APIView): # View
                pass

        c. 无用

            from api.utils.serializsers.pager import PagerSerialiser
            from rest_framework.generics import GenericAPIView

            class View1View(GenericAPIView): # APIView
                queryset = models.Role.objects.all()
                serializer_class = PagerSerialiser
                pagination_class = PageNumberPagination
                def get(self,request,*args,**kwargs):
                    # 获取数据
                    roles = self.get_queryset() # models.Role.objects.all()

                    # [1, 1000,]     [1,10]
                    pager_roles = self.paginate_queryset(roles)

                    # 序列化
                    ser = self.get_serializer(instance=pager_roles,many=True)

                    return Response(ser.data)

        d. GenericViewSet(ViewSetMixin, generics.GenericAPIView):

            路由:
                url(r^(?P<version>[v1|v2]+)/v1/$, views.View1View.as_view({get: list})),

            视图:
                from api.utils.serializsers.pager import PagerSerialiser
                from rest_framework.viewsets import GenericViewSet

                class View1View(GenericViewSet):
                    queryset = models.Role.objects.all()
                    serializer_class = PagerSerialiser
                    pagination_class = PageNumberPagination

                    def list(self, request, *args, **kwargs):
                        # 获取数据
                        roles = self.get_queryset()  # models.Role.objects.all()

                        # [1, 1000,]     [1,10]
                        pager_roles = self.paginate_queryset(roles)

                        # 序列化
                        ser = self.get_serializer(instance=pager_roles, many=True)

                        return Response(ser.data)

        e.
            路由系统:
                url(r^(?P<version>[v1|v2]+)/v1/$, views.View1View.as_view({get: list,post:create})),
                url(r^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$, views.View1View.as_view({get: retrieve,delete:destroy,put:update,patch:partial_update})),

            视图:
                from api.utils.serializsers.pager import PagerSerialiser
                from rest_framework.viewsets import GenericViewSet,ModelViewSet
                from rest_framework.mixins import ListModelMixin,CreateModelMixin

                class View1View(ModelViewSet):
                    queryset = models.Role.objects.all()
                    serializer_class = PagerSerialiser
                    pagination_class = PageNumberPagination

                PS: class View1View(CreateModelMixin,GenericViewSet):
        总结:
            a. 增删改查 ModelViewSet
            b. 增删     CreateModelMixin,DestroyModelMixin  GenericViewSet
            c. 复杂逻辑  GenericViewSet 或 APIView

            PS: 还债:
                GenericAPIView.get_object
                    check_object_permissions
                        has_object_permission

    3. 路由
        a.
            url(r^(?P<version>[v1|v2]+)/parser/$, views.ParserView.as_view()),

        b.
            url(r^(?P<version>[v1|v2]+)/v1/$, views.View1View.as_view({get: list,post:create})),

        c.
            # http://127.0.0.1:8000/api/v1/v1/?format=json
            url(r^(?P<version>[v1|v2]+)/v1/$, views.View1View.as_view({get: list,post:create})),
            # http://127.0.0.1:8000/api/v1/v1.json
            url(r^(?P<version>[v1|v2]+)/v1\.(?P<format>\w+)$, views.View1View.as_view({get: list,post:create})),

            url(r^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)/$, views.View1View.as_view({get: retrieve,delete:destroy,put:update,patch:partial_update})),
            url(r^(?P<version>[v1|v2]+)/v1/(?P<pk>\d+)\.(?P<format>\w+)$, views.View1View.as_view({get: retrieve,delete:destroy,put:update,patch:partial_update})),
        d.
            from api import views
            from rest_framework import routers


            router = routers.DefaultRouter()
            router.register(rxxxxx, views.View1View)
            router.register(rrt, views.View1View)

            urlpatterns = [
                url(r^(?P<version>[v1|v2]+)/, include(router.urls)),
            ]

    4. 渲染
        from rest_framework.renderers import JSONRenderer,BrowsableAPIRenderer

        class TestView(APIView):
            # renderer_classes = [JSONRenderer,BrowsableAPIRenderer]
            def get(self, request, *args, **kwargs):
                # 获取所有数据
                roles = models.Role.objects.all()

                # 创建分页对象
                # pg = CursorPagination()
                pg = MyCursorPagination()

                # 在数据库中获取分页的数据
                pager_roles = pg.paginate_queryset(queryset=roles, request=request, view=self)

                # 对数据进行序列化
                ser = PagerSerialiser(instance=pager_roles, many=True)

                return Response(ser.data)


        REST_FRAMEWORK = {
            "DEFAULT_VERSIONING_CLASS":"rest_framework.versioning.URLPathVersioning",
            "DEFAULT_VERSION":v1,
            "ALLOWED_VERSIONS":[v1,v2],
            "VERSION_PARAM":version,
            "DEFAULT_PARSER_CLASSES":[rest_framework.parsers.JSONParser,rest_framework.parsers.FormParser],
            "PAGE_SIZE":2,

            "DEFAULT_RENDERER_CLASSES":[
                rest_framework.renderers.JSONRenderer,
                rest_framework.renderers.BrowsableAPIRenderer,
            ]
        }

    5. django组件:contenttype

 

rest_framework

标签:普通用户   get   获取   分页   outer   war   角色   序列   click   

原文地址:https://www.cnblogs.com/BensonChang/p/9245727.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!