【亚洲必赢官网】python之Django rest_framework总计

一、rest api

python之Django rest_framework总结,

一、rest api

   a、api正是接口

        如: –

               –

   b、api的三个用途

        1、为外人提供劳动

        二、前后端分离

二、restful

    a、–字面意思:表征状态转移

    b、面向能源编制程序,对互连网上的任性东西都视为能源

         如:-

                –

三、restful规范

     a、 —URL

     b、 —url名词

路径,视网络上任何东西都是资源,均使用名词表示(可复数)
  https://api.example.com/v1/zoos
  https://api.example.com/v1/animals
  https://api.example.com/v1/employee

    c、 —status状态码**

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

   d、—提交情势

GET      :从服务器取出资源(一项或多项)
POST    :在服务器新建一个资源
PUT      :在服务器更新资源(客户端提供改变后的完整资源)
PATCH  :在服务器更新资源(客户端提供改变的属性)
DELETE :从服务器删除资源

   e、  —错误音信

状态码是4xx时,应返回错误信息,error当做key。
{
    error: "Invalid API key"
}

   f、 —版本**

   g、 —Hypermedia link,RESTful
API最棒成功Hypermedia,即重返结果中提供链接,连向其余API方法,使得用户不查文书档案,也明白下一步应该做什么。

   h、—域名**

   j、—过滤,通过在url上传参的情势传递搜索条件**

 
k、 
—再次来到结果,针对不一样操作,服务器向用户重回的结果应当符合以下标准**

GET /collection:返回资源对象的列表(数组)  
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

rest_Framework的规范:

   
按顺序:它的method的两样,原来未有考虑,原来是url区分,以往通过method来分别,method的不及提交格局各异,紧接着1般是面向财富的就是把url变成名词,接下便是再次回到值,在此在此之前并未有思量状态码,以后有怀念状态码。(一般有get,post方法,还有put,delete等办法)

**4、 基于Django Rest Framework框架落成 **

   a、安装:pip3 install djangorestframework -i
–trusted-host=pypi.douban.com

五、什么是RESTful

  • REST与技能非亲非故,代表的是一种软件架构风格,REST是Representational
    State Transfer的简称,中文翻译为“表征状态转移”
  • REST从能源的角度类审视整个网络,它将分布在网络中有些节点的能源通过U酷路泽L举行标识,客户端应用通过ULacrosseL来收获财富的性状,获得这个特点致使这一个应用转变状态
  • REST与技能非亲非故,代表的是一种软件框架结构风格,REST是Representational
    State Transfer的简称,汉译为“表征状态转移”
  • 有着的数码,不过是因而网络获取的也许操作(增加和删除改查)的多少,都是能源,将整个数据就是财富是REST不相同与别的架构风格的最本质属性
  • 对此REST那种面向财富的架构风格,有人建议1种崭新的协会理念,即:面向能源架构(ROA:Resource
    Oriented Architecture)

      a、 django的中间件比rest_framework执行的早**

      b、 认证的功用放到中间件也是足以做的**

     
c、
证实一般做,检查用户是不是存在,若是存在request.user/request.auth;不设有request.user/request.auth=None**

      d、表明小总括:**

  ---类:authenticate/authenticate_header

      ---返回值:None,元组(user,auth),异常

      ---配置:

                 ---视图:                      

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

                 ---全局                    

                                    REST_FRAMEWORK = {
                                                'UNAUTHENTICATED_USER': None,
                                                'UNAUTHENTICATED_TOKEN': None,
                                                "DEFAULT_AUTHENTICATION_CLASSES": [
                                                 # "app02.utils.MyAuthentication",
                                                ],
                                               }

六、权限

   
a、
权限才真的的做request.user/request.auth得到它们做是否访问的论断**

    b、权力小计算: **

     ---类:       has_permission/has_object_permission

     ---返回值:True、False、exceptions.PermissionDenied(detail="错误信息")

     ---配置:

               ---视图:                  

                                class IndexView(APIView):
                                       permission_classes = [MyPermission,]

                      ---全局:

                                REST_FRAMEWORK = {
                                "DEFAULT_PERMISSION_CLASSES": [
                                # "app02.utils.MyAuthentication",
                                 ],
                               }

7、限制访问的频率

    限制访问频率的施用:

   a、对匿名用户展开界定,每一种用户一分钟允许访问十四次

        在此间用唯一标识:self.get_ident() 

   b、限制访问的频率小总括: **

  ---类:       allow_request/wait PS: scope = "wdp_user"

     ---返回值:True、False

     ---配置:

                  ---视图:

                                            class IndexView(APIView):
                                                     throttle_classes=[AnonThrottle,UserThrottle,]
                                                     def get(self,request,*args,**kwargs):
                                                     self.dispatch
                                                     return Response('访问首页')

                   ---全局:

                                          REST_FRAMEWORK = {
                                                      "DEFAULT_THROTTLE_CLASSES":[
                                                   ],
                                                      'DEFAULT_THROTTLE_RATES':{
                                                      'wdp_anon':'5/minute',
                                                      'wdp_user':'10/minute',
                                                   }
                                                   }

、认证、权限、限制访问频率重回结果的可比

    1、注脚、权限、限制访问频率那多少个重临的结果:**

**     a、评释重返的二种结果:             a、None             b、元组(user,auth)             c、异常 raise APIException(…)**

**     b、 权限的重回值二种结果:**

**            a、True 有权限             b、False 没权限             c、异常**

**     c、 限制访问的作用重回值的三种结果:**

**            a、True 
            b、False**

实例化:
v1 = ["view.xxx.path.Role","view.xxx.path.Group",]    可以循环,循环出来的每一个不能实例化
如果把v1循环弄成每一个对象列表,通过rsplit切割,在通过importlib.import_module拿到每一个路径,在通过getattr把它的类名拿过来,
这个类加括号就是实例化想
for item in v1:
m = importlib.import_module('view.xxx.path')
cls = getattr(m,'Role')
cls()



from view.xxx.path import Role,Group      
v2 = [Group,Role]      这个可以循环每一个实例化
for item in v2:     #循环V2的每一个元素加括号,就是实例化
item()

九、Django rest_Framework框架

     a、  —-为何用Django rest_Framework框架?**

----首先没有Django rest_Framework框架用django也是可以做出来的,只不过它为我们提供一些API常用的功能,比如:(认证,权限,限流,有了这些我们只需要写个类已配置,
它就能当都市图用,还能全局配置,如果自己写还得写中间件,写装饰器来实现,通过Django rest_Framework框架,他已经把规则写好,只需要写类,只需实现方法,返回值就可以)
实现了一部分功能。

  ----设计比较好

            ----单独视图+全局配置 =>Dajngo中间件(importlib/反射)=>动态配置课扩展(短信,邮件,微信等提醒)

     b、Django rest_Framework原理?

             先伊始在路由,路由.as_view,

             点击as_view**

**             伸手进入,走完以上,才走self.dispatch()**

           
 走
self.dispatch()流程如下地址: 

十、版本

**    a、依照url的例外来来操作,版本控制**

**          先在setting中注册**

*【亚洲必赢官网】python之Django rest_framework总计。*十一、rest framework解析器**

**   
a、呼吁的数额实行解析:请求体进行解析。表示服务端能够分析的多寡格式的品类。**

Content-Type: application/url-encoding.....
            request.body
            request.POST

            Content-Type: application/json.....
            request.body
            request.POST

        客户端:
            Content-Type: application/json
            '{"name":"alex","age":123}'

        服务端接收:
            读取客户端发送的Content-Type的值 application/json

            parser_classes = [JSONParser,]
            media_type_list = ['application/json',]

            如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
            如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据


        配置:
            单视图:
            class UsersView(APIView):
                parser_classes = [JSONParser,]

            全局配置:
                REST_FRAMEWORK = {
                    'VERSION_PARAM':'version',
                    'DEFAULT_VERSION':'v1',
                    'ALLOWED_VERSIONS':['v1','v2'],
                    # 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"
                    'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
                    'DEFAULT_PARSER_CLASSES':[
                        'rest_framework.parsers.JSONParser',
                        'rest_framework.parsers.FormParser',
                    ]
                }

十二、 rest framework序列化+Form

     a、序列化:

               对象 -> 字符串 序列化                字符串 -> 对象 反体系化**

**     b、目的:                解决QuerySet系列化问题**

**十三、何以要上下端分离**

**    a、因为前端它有友好框架,那样它的作用就可怜高**

**   
b、不做上下端分离,公司只要既有客户端,又有app那种景观下您就的写五遍**

**十四、django restful框架好处**

  帮忙大家写了众多组件比如:

   
 a、认证:有类,类中的方法
authenticate/authenticate_header,它的重返值有None,元组,很是。要是重回值为None那就不管,它是匿名用户。**

     b、权限:有类,类中的方法:has_permission**

   
 c、节流:有类,类的法子:allow_request,在这里allow_request来表示限制,它是透过IP来界定,

 它的内部原理是:默认是IP,用户来用IP,这个IP可能代理IP,IP或者是代理IP拿着请求头默认放到大家能够的缓存中                          
去,每一个人的IP为p,后面的那个列表存它的方位时间,每一次请求进来获取它的当前时间根据时间的个数来比较,在                        
比较的过程中看看把不符合时间的个数来进行比较,能访问就继续,不能访问就不要继续。 

   
 d、版本:是url和hostname,他们多个钟每3个都有多少个章程3个是帮您拿版本另一个是帮你反向生成url

     e、解析器:用户发过来的请求体数据开始展览操作

     f、类别化:五个职能:体系化,校验

十五、分页

分页的三种情状:

       a、记录当前访问页的数据id

       b、最多展现120页

       c、对页码进行加密

a、基于limit offset做分页

class P1(LimitOffsetPagination):

                max_limit = 3
                default_limit = 2
                limit_query_param = 'limit'
                offset_query_param = 'offset'


            class IndexView(views.APIView):
                def get(self,request,*args,**kwargs):
                    user_list = models.UserInfo.objects.all()
                    p1 = P1()
                    page_user_list = p1.paginate_queryset(queryset=user_list, request=request, view=self)
                    ser = IndexSerializer(instance=page_user_list, many=True)
                    return Response(ser.data) # 不含上一页和下一页
                    # return p1.get_paginated_response(ser.data) # 含上一页和下一页

            class IndexView(views.APIView):
                def get(self,request,*args,**kwargs):
                    ret = BaseResponse()
                    try:
                        user_list = models.UserInfo.objects.all()
                        p1 = P1()
                        page_user_list = p1.paginate_queryset(queryset=user_list,request=request,view=self)
                        ser = IndexSerializer(instance=page_user_list,many=True)
                        ret.data = ser.data
                        ret.next = p1.get_next_link()
                    except Exception as e:
                        ret.code= 1001
                        ret.error = 'xxxx错误'
                    return Response(ret.__dict__)

 b. 基于页码的分页

class P2(PageNumberPagination):
                # 每页显示的数据条数
                max_page_size = 5
                page_size = 2
                page_size_query_param = 'size'

                # 页码
                page_query_param = 'page'

十六、视图

1、APIView

class IndexView(views.APIView):
                    def get(self, request, *args, **kwargs):
                        user_list = models.UserInfo.objects.all()
                        ser = IndexSerializer(instance=user_list,many=True)
                        return Response(ser.data)

2、GenericAPIview(APIView)

3、GenericViewSet(ViewSetMixin,generics.GenericAPIView)

路由修改:
                    urlpatterns = [
                        url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})),
                        url(r'^index/(?P<pk>\d+)$', views.IndexView.as_view({'get':'retrieve'})),
                    ]

                视图修改:

                    class IndexView(viewsets.GenericViewSet):

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

                             pass # 获取列表信息

                        def retrieve(self, request, *args, **kwargs):
                            pass  # 获取单条数据

                        def create(self,request, *args, **kwargs):
                            pass


                自定义:

                        增
                            POST
                            /users/
                        删
                            DELETE
                            /users/1/
                        改
                            PUT
                            /users/1/

                            patch
                            /users/1/
                        查
                            GET
                            /users/ 
                            GET
                            /users/1/

                        urlpatterns = [

                            url(r'^index/$', views.IndexView.as_view()),
                            url(r'^index/(?P<pk>\d+)$', views.IndexView.as_view()),
                        ]

                        class IndexView(views.APIView):

                            def get(self,request,*args,**kwargs):
                                pk = kwargs.get('pk')
                                if pk:
                                    pass # 获取单条信息
                                else:
                                    pass # 获取列表信息

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

                            def put(self,request,*args,**kwargs):
                                pass

                            def patch(self,request,*args,**kwargs):
                                pass

                            def delete(self,request,*args,**kwargs):
                                pass

4、ModelViewSet

ModelViewSet(mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet)                

                class IndexView(ModelViewSet):

十七、 渲染器
    看到的页面时怎么体统的,重临数据。
    renderer_classes = [JSONRenderer,BrowsableAPIRenderer]

十八、跨域

   a、  浏览器的同源策略

              一、  —-对ajax请求实行阻挠

               二、 —-对href属性读不阻拦

       xhr=new XMLHttpRequest

       xhr.open…

       xhr.send(…)

    b、 消除方案:

         —JSONP

                 点击按钮: 

                        动态增进二个

<script src='http://www.baidu.com/users/'></script>
                        <script>
                            function func(arg){
                                alert(arg)
                            }
                        </script

    c、删除

<script src='http://www.baidu.com/users/'></script>

 

rest_framework计算, 壹、rest api
a、api正是接口 如: – –
b、api的多少个用途…

Django Rest Framework

Django Rest Framework

 

   a、api正是接口

一、什么是RESTful

  • REST与技术无关,代表的是一种软件架构风格,REST是Representational
    State Transfer的简称,中文翻译为“表征状态转移”

  • REST从能源的角度类审视整个互连网,它将分布在网络中某些节点的资源通过U福特ExplorerL实行标识,客户端应用通过UCR-VL来收获能源的性状,获得这一个特色致使那几个应用转变状态

  • 享有的多少,但是是透过互连网获得的依旧操作(增加和删除改查)的数据,都以财富,将全部数据正是能源是REST不一致与其余架构风格的最本质属性

  • 对于REST那种面向财富的架构风格,有人指出1种全新的构造理念,即:面向财富架构(ROA:Resource
    Oriented Architecture)

一. 什么是RESTful 

  • REST与技能非亲非故,代表的是一种软件框架结构风格,REST是Representational
    State Transfer的简称,粤语翻译为“表征状态转移”
  • REST从能源的角度类审视整个互连网,它将分布在互联网中有些节点的能源通过U景逸SUVL举办标识,客户端应用通过U陆风X8L来获取能源的风味,获得这么些特征致使那几个应用转变状态
  • REST与技能非亲非故,代表的是一种软件架构风格,REST是Representational
    State Transfer的简称,中文翻译为“表征状态转移”
  • 怀有的数量,但是是经过网络获取的要么操作(增加和删除改查)的数码,都以资源,将全部数据正是财富是REST分裂与任何架构风格的最本质属性
  • 对此REST那种面向能源的架构风格,有人建议一种崭新的结构理念,即:面向能源架构(ROA:Resource
    Oriented Architecture)

        如: –

二、RESTful API设计

API与用户的通讯协议,总是利用HTTPs协议。

域名

  • 尽量将API安排在专用域名(会设有跨域难题)

  • API很简单

版本

  • URL,如:

  • 恳请头 跨域时,引发发送多次呼吁

途径,视网络上其余东西都以财富,均选用名词意味着(可复数)

method

  • GET :从服务器取出能源(一项或多项)
  • POST :在服务器新建二个能源
  • PUT :在服务器更新能源(客户端提供改变后的完好能源)
  • PATCH :在服务器更新能源(客户端提供改变的品质)
  • DELETE :从服务器删除能源

过滤,通过在url上传参的款型传递搜索条件

  • https://api.example.com/v1/zoos?limit=10:钦赐再次来到记录的数据
  • https://api.example.com/v1/zoos?offset=拾:钦命重回记录的初步地方
  • https://api.example.com/v1/zoos?page=2&per\_page=十0:钦定第几页,以及每页的记录数
  • https://api.example.com/v1/zoos?sortby=name&order=asc:钦命重返结果依照哪个属性排序,以及排序依次
  • https://api.example.com/v1/zoos?animal\_type\_id=壹:钦命筛选标准

状态码

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html

错误处理,状态码是4xx时,应重返错误音信,error当做key。

{
    error: "Invalid API key"
}

归来结果,针对分歧操作,服务器向用户再次来到的结果应当符合以下标准。

GET /collection:返回资源对象的列表(数组)
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

Hypermedia API,RESTful
API最棒成功Hypermedia,即重回结果中提供链接,连向此外API方法,使得用户不查文书档案,也知晓下一步应该做什么样。

{"link": {
  "rel":   "collection https://www.example.com/zoos",
  "href":  "https://api.example.com/zoos",
  "title": "List of zoos",
  "type":  "application/vnd.yourformat+json"
}}

摘自:

三、基于Django实现

路由系统:

urlpatterns = [
    url(r'^users', Users.as_view()),
]

CBV视图:

from django.views import View
from django.http import JsonResponse

class Users(View):
    def get(self, request, *args, **kwargs):
        result = {
            'status': True,
            'data': 'response data'
        }
        return JsonResponse(result, status=200)

    def post(self, request, *args, **kwargs):
        result = {
            'status': True,
            'data': 'response data'
        }
        return JsonResponse(result, status=200)

二. RESTful API设计

  • API与用户的通信协议,总是利用HTTPs协议。
  • 域名 
    •  
                           
       尽量将API铺排在专用域名(会设有跨域难题)
    •  
                            API很简单
  • 版本
    • URL,如:
    • 请求头           
                                           
      跨域时,引发发送数十次请求
  • 途径,视互连网上任刘亚辉西都以能源,均选用名词意味着(可复数)
  • method
    • GET     
      :从服务器取出能源(一项或多项)
    • POST   
      :在服务器新建一个财富
    • PUT     
      :在服务器更新财富(客户端提供改变后的完好能源)
    • PATCH 
      :在服务器更新能源(客户端提供改变的属性)
    • DELETE
      :从服务器删除财富
  • 过滤,通过在url上传参的款式传递搜索条件
  • 状态码
    亚洲必赢官网 1亚洲必赢官网 2

    200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
    201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
    202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
    204 NO CONTENT - [DELETE]:用户删除数据成功。
    400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
    401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
    403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
    404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
    406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
    410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
    422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
    500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。
    
    更多看这里:http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html
    

    常用状态码列表

  • 错误处理,状态码是四xx时,应再次回到错误音讯,error当做key。

    {
        error: "Invalid API key"
    }
    
  • 重回结果,针对不一样操作,服务器向用户重返的结果应该符合以下标准。

    GET /collection:返回资源对象的列表(数组)
    GET /collection/resource:返回单个资源对象
    POST /collection:返回新生成的资源对象
    PUT /collection/resource:返回完整的资源对象
    PATCH /collection/resource:返回完整的资源对象
    DELETE /collection/resource:返回一个空文档
    
  • Hypermedia API,RESTful
    API最好达成Hypermedia,即再次回到结果中提供链接,连向任何API方法,使得用户不查文书档案,也晓得下一步应该做怎么着。

    {"link": {
      "rel":   "collection https://www.example.com/zoos",
      "href":  "https://api.example.com/zoos",
      "title": "List of zoos",
      "type":  "application/vnd.yourformat+json"
    }}
    

  摘自: 

               –

4、基于Django Rest Framework框架完结

三. 基于Django实现

路由系统:

urlpatterns = [
    url(r'^users', Users.as_view()),
]

CBV视图:

from django.views import View
from django.http import JsonResponse

class Users(View):
    def get(self, request, *args, **kwargs):
        result = {
            'status': True,
            'data': 'response data'
        }
        return JsonResponse(result, status=200)

    def post(self, request, *args, **kwargs):
        result = {
            'status': True,
            'data': 'response data'
        }
        return JsonResponse(result, status=200) 

   b、api的七个用途

壹、基本流程

url.py

from django.conf.urls import url, include
from web.views.s1_api import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

views.py

from rest_framework.views import APIView
from rest_framework.response import Response


class TestView(APIView):
    def dispatch(self, request, *args, **kwargs):
        """
        请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发 get/post/put等方法

        注意:APIView中的dispatch方法有好多好多的功能
        """
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

上述是rest
framework框架基本流程,重要的效劳是在APIView的dispatch中触发。

4. 基于Django Rest Framework框架实现

        一、为人家提供劳务

贰.证实和授权

a. 用户url传入的token认证

  • urls.py

    from django.conf.urls import url, include
    from web.viewsimport TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
  • views.py

    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.request import Request
    from rest_framework import exceptions
    
    token_list = [
        'sfsfss123kuf3j123',
        'asijnfowerkkf9812',
    ]
    
    class TestAuthentication(BaseAuthentication):
        def authenticate(self, request):
            """
            用户认证,如果验证成功后返回元组: (用户,用户Token)
            :param request: 
            :return: 
                None,表示跳过该验证;
                    如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                    self._authenticator = None
                    if api_settings.UNAUTHENTICATED_USER:
                        self.user = api_settings.UNAUTHENTICATED_USER()
                    else:
                        self.user = None

                    if api_settings.UNAUTHENTICATED_TOKEN:
                        self.auth = api_settings.UNAUTHENTICATED_TOKEN()
                    else:
                        self.auth = None
                (user,token)表示验证通过并设置用户名和Token;
                AuthenticationFailed异常
            """
            val = request.query_params.get('token')
            if val not in token_list:
                raise exceptions.AuthenticationFailed("用户认证失败")

            return ('登录用户', '用户token')

        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            # 验证失败时,返回的响应头WWW-Authenticate对应的值
            pass


    class TestView(APIView):
        authentication_classes = [TestAuthentication, ]
        permission_classes = []

        def get(self, request, *args, **kwargs):
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

b. 请求头认证

  • urls.py

    from django.conf.urls import url, include
    from web.viewsimport TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.request import Request
    from rest_framework import exceptions
    
    token_list = [
        'sfsfss123kuf3j123',
        'asijnfowerkkf9812',
    ]
    
    class TestAuthentication(BaseAuthentication):
        def authenticate(self, request):
            """
            用户认证,如果验证成功后返回元组: (用户,用户Token)
            :param request: 
            :return: 
                None,表示跳过该验证;
                    如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                    self._authenticator = None
                    if api_settings.UNAUTHENTICATED_USER:
                        self.user = api_settings.UNAUTHENTICATED_USER()
                    else:
                        self.user = None

                    if api_settings.UNAUTHENTICATED_TOKEN:
                        self.auth = api_settings.UNAUTHENTICATED_TOKEN()
                    else:
                        self.auth = None
                (user,token)表示验证通过并设置用户名和Token;
                AuthenticationFailed异常
            """
            import base64
            auth = request.META.get('HTTP_AUTHORIZATION', b'')
            if auth:
                auth = auth.encode('utf-8')
            auth = auth.split()
            if not auth or auth[0].lower() != b'basic':
                raise exceptions.AuthenticationFailed('验证失败')
            if len(auth) != 2:
                raise exceptions.AuthenticationFailed('验证失败')
            username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')
            if username == 'alex' and password == '123':
                return ('登录用户', '用户token')
            else:
                raise exceptions.AuthenticationFailed('用户名或密码错误')

        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            return 'Basic realm=api'


    class TestView(APIView):
        authentication_classes = [TestAuthentication, ]
        permission_classes = []

        def get(self, request, *args, **kwargs):
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

c.四个验证规则

  • urls.py

    from django.conf.urls import url, include
    from web.views.s2_auth import TestView

    urlpatterns = [
    url(r’^test/’, TestView.as_view()),]

  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.request import Request
    from rest_framework import exceptions
    
    token_list = [
        'sfsfss123kuf3j123',
        'asijnfowerkkf9812',
    ]
    
    class Test1Authentication(BaseAuthentication):
        def authenticate(self, request):
            """
            用户认证,如果验证成功后返回元组: (用户,用户Token)
            :param request: 
            :return: 
                None,表示跳过该验证;
                    如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                    self._authenticator = None
                    if api_settings.UNAUTHENTICATED_USER:
                        self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
                    else:
                        self.user = None

                    if api_settings.UNAUTHENTICATED_TOKEN:
                        self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
                    else:
                        self.auth = None
                (user,token)表示验证通过并设置用户名和Token;
                AuthenticationFailed异常
            """
            import base64
            auth = request.META.get('HTTP_AUTHORIZATION', b'')
            if auth:
                auth = auth.encode('utf-8')
            else:
                return None
            print(auth,'xxxx')
            auth = auth.split()
            if not auth or auth[0].lower() != b'basic':
                raise exceptions.AuthenticationFailed('验证失败')
            if len(auth) != 2:
                raise exceptions.AuthenticationFailed('验证失败')
            username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')
            if username == 'alex' and password == '123':
                return ('登录用户', '用户token')
            else:
                raise exceptions.AuthenticationFailed('用户名或密码错误')

        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            # return 'Basic realm=api'
            pass

    class Test2Authentication(BaseAuthentication):
        def authenticate(self, request):
            """
            用户认证,如果验证成功后返回元组: (用户,用户Token)
            :param request: 
            :return: 
                None,表示跳过该验证;
                    如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                    self._authenticator = None
                    if api_settings.UNAUTHENTICATED_USER:
                        self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
                    else:
                        self.user = None

                    if api_settings.UNAUTHENTICATED_TOKEN:
                        self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
                    else:
                        self.auth = None
                (user,token)表示验证通过并设置用户名和Token;
                AuthenticationFailed异常
            """
            val = request.query_params.get('token')
            if val not in token_list:
                raise exceptions.AuthenticationFailed("用户认证失败")

            return ('登录用户', '用户token')

        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            pass


    class TestView(APIView):
        authentication_classes = [Test1Authentication, Test2Authentication]
        permission_classes = []

        def get(self, request, *args, **kwargs):
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

d.认证和权力

  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView

    urlpatterns = [
    url(r’^test/’, TestView.as_view()),]

  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.authentication import BaseAuthentication
    from rest_framework.permissions import BasePermission
    
    from rest_framework.request import Request
    from rest_framework import exceptions
    
    token_list = [
        'sfsfss123kuf3j123',
        'asijnfowerkkf9812',
    ]
    
    class TestAuthentication(BaseAuthentication):
        def authenticate(self, request):
            """
            用户认证,如果验证成功后返回元组: (用户,用户Token)
            :param request: 
            :return: 
                None,表示跳过该验证;
                    如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                    self._authenticator = None
                    if api_settings.UNAUTHENTICATED_USER:
                        self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
                    else:
                        self.user = None

                    if api_settings.UNAUTHENTICATED_TOKEN:
                        self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
                    else:
                        self.auth = None
                (user,token)表示验证通过并设置用户名和Token;
                AuthenticationFailed异常
            """
            val = request.query_params.get('token')
            if val not in token_list:
                raise exceptions.AuthenticationFailed("用户认证失败")

            return ('登录用户', '用户token')

        def authenticate_header(self, request):
            """
            Return a string to be used as the value of the `WWW-Authenticate`
            header in a `401 Unauthenticated` response, or `None` if the
            authentication scheme should return `403 Permission Denied` responses.
            """
            pass


    class TestPermission(BasePermission):
        message = "权限验证失败"

        def has_permission(self, request, view):
            """
            判断是否有权限访问当前请求
            Return `True` if permission is granted, `False` otherwise.
            :param request: 
            :param view: 
            :return: True有权限;False无权限
            """
            if request.user == "管理员":
                return True

        # GenericAPIView中get_object时调用
        def has_object_permission(self, request, view, obj):
            """
            视图继承GenericAPIView,并在其中使用get_object时获取对象时,触发单独对象权限验证
            Return `True` if permission is granted, `False` otherwise.
            :param request: 
            :param view: 
            :param obj: 
            :return: True有权限;False无权限
            """
            if request.user == "管理员":
                return True


    class TestView(APIView):
        # 认证的动作是由request.user触发
        authentication_classes = [TestAuthentication, ]

        # 权限
        # 循环执行所有的权限
        permission_classes = [TestPermission, ]

        def get(self, request, *args, **kwargs):
            # self.dispatch
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

e. 全局使用

上述操作中均是对独立视图实行相当规布署,借使想要对全局实行安顿,则必要再配置文件中写入即可

  • settings.py

    REST_FRAMEWORK = {
        'UNAUTHENTICATED_USER': None,
        'UNAUTHENTICATED_TOKEN': None,
        "DEFAULT_AUTHENTICATION_CLASSES": [
            "web.utils.TestAuthentication",
        ],
        "DEFAULT_PERMISSION_CLASSES": [
            "web.utils.TestPermission",
        ],
    }
    
  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    class TestView(APIView):
    
        def get(self, request, *args, **kwargs):
            # self.dispatch
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')
    
        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')
    
        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
    

一. 为主流程

url.py

from django.conf.urls import url, include
from web.views.s1_api import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

views.py

from rest_framework.views import APIView
from rest_framework.response import Response


class TestView(APIView):
    def dispatch(self, request, *args, **kwargs):
        """
        请求到来之后,都要执行dispatch方法,dispatch方法根据请求方式不同触发 get/post/put等方法

        注意:APIView中的dispatch方法有好多好多的功能
        """
        return super().dispatch(request, *args, **kwargs)

    def get(self, request, *args, **kwargs):
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

上述是rest
framework框架基本流程,首要的机能是在APIView的dispatch中触发。

        二、前后端分离

三. 用户访问次数/频率限制

  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    import time
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from rest_framework import exceptions
    from rest_framework.throttling import BaseThrottle
    from rest_framework.settings import api_settings
    
    # 保存访问记录
    RECORD = {
        '用户IP': [12312139, 12312135, 12312133, ]
    }
    
    class TestThrottle(BaseThrottle):
        ctime = time.time

        def get_ident(self, request):
            """
            根据用户IP和代理IP,当做请求者的唯一IP
            Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
            if present and number of proxies is > 0. If not use all of
            HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
            """
            xff = request.META.get('HTTP_X_FORWARDED_FOR')
            remote_addr = request.META.get('REMOTE_ADDR')
            num_proxies = api_settings.NUM_PROXIES

            if num_proxies is not None:
                if num_proxies == 0 or xff is None:
                    return remote_addr
                addrs = xff.split(',')
                client_addr = addrs[-min(num_proxies, len(addrs))]
                return client_addr.strip()

            return ''.join(xff.split()) if xff else remote_addr

        def allow_request(self, request, view):
            """
            是否仍然在允许范围内
            Return `True` if the request should be allowed, `False` otherwise.
            :param request: 
            :param view: 
            :return: True,表示可以通过;False表示已超过限制,不允许访问
            """
            # 获取用户唯一标识(如:IP)

            # 允许一分钟访问10次
            num_request = 10
            time_request = 60

            now = self.ctime()
            ident = self.get_ident(request)
            self.ident = ident
            if ident not in RECORD:
                RECORD[ident] = [now, ]
                return True
            history = RECORD[ident]
            while history and history[-1] <= now - time_request:
                history.pop()
            if len(history) < num_request:
                history.insert(0, now)
                return True

        def wait(self):
            """
            多少秒后可以允许继续访问
            Optionally, return a recommended number of seconds to wait before
            the next request.
            """
            last_time = RECORD[self.ident][0]
            now = self.ctime()
            return int(60 + last_time - now)


    class TestView(APIView):
        throttle_classes = [TestThrottle, ]

        def get(self, request, *args, **kwargs):
            # self.dispatch
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

        def throttled(self, request, wait):
            """
            访问次数被限制时,定制错误信息
            """

            class Throttled(exceptions.Throttled):
                default_detail = '请求被限制.'
                extra_detail_singular = '请 {wait} 秒之后再重试.'
                extra_detail_plural = '请 {wait} 秒之后再重试.'

            raise Throttled(wait)

b. 基于用户IP突显访问频率(利于Django缓存)

  • settings.py

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_RATES': {
            'test_scope': '10/m',
        },
    }
    
  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from rest_framework import exceptions
    from rest_framework.throttling import SimpleRateThrottle
    
    class TestThrottle(SimpleRateThrottle):

        # 配置文件定义的显示频率的Key
        scope = "test_scope"

        def get_cache_key(self, request, view):
            """
            Should return a unique cache-key which can be used for throttling.
            Must be overridden.

            May return `None` if the request should not be throttled.
            """
            if not request.user:
                ident = self.get_ident(request)
            else:
                ident = request.user

            return self.cache_format % {
                'scope': self.scope,
                'ident': ident
            }


    class TestView(APIView):
        throttle_classes = [TestThrottle, ]

        def get(self, request, *args, **kwargs):
            # self.dispatch
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

        def throttled(self, request, wait):
            """
            访问次数被限制时,定制错误信息
            """

            class Throttled(exceptions.Throttled):
                default_detail = '请求被限制.'
                extra_detail_singular = '请 {wait} 秒之后再重试.'
                extra_detail_plural = '请 {wait} 秒之后再重试.'

            raise Throttled(wait)

c. view中限制请求频率

  • settings.py

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_RATES': {
            'xxxxxx': '10/m',
        },
    }
    
  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from rest_framework import exceptions
    from rest_framework.throttling import ScopedRateThrottle
    
    # 继承 ScopedRateThrottle
    class TestThrottle(ScopedRateThrottle):

        def get_cache_key(self, request, view):
            """
            Should return a unique cache-key which can be used for throttling.
            Must be overridden.

            May return `None` if the request should not be throttled.
            """
            if not request.user:
                ident = self.get_ident(request)
            else:
                ident = request.user

            return self.cache_format % {
                'scope': self.scope,
                'ident': ident
            }


    class TestView(APIView):
        throttle_classes = [TestThrottle, ]

        # 在settings中获取 xxxxxx 对应的频率限制值
        throttle_scope = "xxxxxx"

        def get(self, request, *args, **kwargs):
            # self.dispatch
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

        def throttled(self, request, wait):
            """
            访问次数被限制时,定制错误信息
            """

            class Throttled(exceptions.Throttled):
                default_detail = '请求被限制.'
                extra_detail_singular = '请 {wait} 秒之后再重试.'
                extra_detail_plural = '请 {wait} 秒之后再重试.'

            raise Throttled(wait)

d. 匿名时用IP限制+登录时用Token限制

  • settings.py

    REST_FRAMEWORK = {
        'UNAUTHENTICATED_USER': None,
        'UNAUTHENTICATED_TOKEN': None,
        'DEFAULT_THROTTLE_RATES': {
            'luffy_anon': '10/m',
            'luffy_user': '20/m',
        },
    }
    
  • urls.py

    from django.conf.urls import url, include
    from web.views.s3_throttling import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    from rest_framework.throttling import SimpleRateThrottle
    
    class LuffyAnonRateThrottle(SimpleRateThrottle):
        """
        匿名用户,根据IP进行限制
        """
        scope = "luffy_anon"

        def get_cache_key(self, request, view):
            # 用户已登录,则跳过 匿名频率限制
            if request.user:
                return None

            return self.cache_format % {
                'scope': self.scope,
                'ident': self.get_ident(request)
            }


    class LuffyUserRateThrottle(SimpleRateThrottle):
        """
        登录用户,根据用户token限制
        """
        scope = "luffy_user"

        def get_ident(self, request):
            """
            认证成功时:request.user是用户对象;request.auth是token对象
            :param request: 
            :return: 
            """
            # return request.auth.token
            return "user_token"

        def get_cache_key(self, request, view):
            """
            获取缓存key
            :param request: 
            :param view: 
            :return: 
            """
            # 未登录用户,则跳过 Token限制
            if not request.user:
                return None

            return self.cache_format % {
                'scope': self.scope,
                'ident': self.get_ident(request)
            }


    class TestView(APIView):
        throttle_classes = [LuffyUserRateThrottle, LuffyAnonRateThrottle, ]

        def get(self, request, *args, **kwargs):
            # self.dispatch
            print(request.user)
            print(request.auth)
            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

e. 全局使用

  • settings

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_CLASSES': [
            'api.utils.throttles.throttles.LuffyAnonRateThrottle',
            'api.utils.throttles.throttles.LuffyUserRateThrottle',
        ],
        'DEFAULT_THROTTLE_RATES': {
            'anon': '10/day',
            'user': '10/day',
            'luffy_anon': '10/m',
            'luffy_user': '20/m',
        },
    }
    

2.  表达和授权

a. 用户url传入的token认证

亚洲必赢官网 3亚洲必赢官网 4

from django.conf.urls import url, include
from web.viewsimport TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 5亚洲必赢官网 6

from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.request import Request
from rest_framework import exceptions

token_list = [
    'sfsfss123kuf3j123',
    'asijnfowerkkf9812',
]


class TestAuthentication(BaseAuthentication):
    def authenticate(self, request):
        """
        用户认证,如果验证成功后返回元组: (用户,用户Token)
        :param request: 
        :return: 
            None,表示跳过该验证;
                如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                self._authenticator = None
                if api_settings.UNAUTHENTICATED_USER:
                    self.user = api_settings.UNAUTHENTICATED_USER()
                else:
                    self.user = None

                if api_settings.UNAUTHENTICATED_TOKEN:
                    self.auth = api_settings.UNAUTHENTICATED_TOKEN()
                else:
                    self.auth = None
            (user,token)表示验证通过并设置用户名和Token;
            AuthenticationFailed异常
        """
        val = request.query_params.get('token')
        if val not in token_list:
            raise exceptions.AuthenticationFailed("用户认证失败")

        return ('登录用户', '用户token')

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        # 验证失败时,返回的响应头WWW-Authenticate对应的值
        pass


class TestView(APIView):
    authentication_classes = [TestAuthentication, ]
    permission_classes = []

    def get(self, request, *args, **kwargs):
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

b. 请求头认证

亚洲必赢官网 7亚洲必赢官网 8

from django.conf.urls import url, include
from web.viewsimport TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 9亚洲必赢官网 10

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.request import Request
from rest_framework import exceptions

token_list = [
    'sfsfss123kuf3j123',
    'asijnfowerkkf9812',
]


class TestAuthentication(BaseAuthentication):
    def authenticate(self, request):
        """
        用户认证,如果验证成功后返回元组: (用户,用户Token)
        :param request: 
        :return: 
            None,表示跳过该验证;
                如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                self._authenticator = None
                if api_settings.UNAUTHENTICATED_USER:
                    self.user = api_settings.UNAUTHENTICATED_USER()
                else:
                    self.user = None

                if api_settings.UNAUTHENTICATED_TOKEN:
                    self.auth = api_settings.UNAUTHENTICATED_TOKEN()
                else:
                    self.auth = None
            (user,token)表示验证通过并设置用户名和Token;
            AuthenticationFailed异常
        """
        import base64
        auth = request.META.get('HTTP_AUTHORIZATION', b'')
        if auth:
            auth = auth.encode('utf-8')
        auth = auth.split()
        if not auth or auth[0].lower() != b'basic':
            raise exceptions.AuthenticationFailed('验证失败')
        if len(auth) != 2:
            raise exceptions.AuthenticationFailed('验证失败')
        username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')
        if username == 'alex' and password == '123':
            return ('登录用户', '用户token')
        else:
            raise exceptions.AuthenticationFailed('用户名或密码错误')

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        return 'Basic realm=api'


class TestView(APIView):
    authentication_classes = [TestAuthentication, ]
    permission_classes = []

    def get(self, request, *args, **kwargs):
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

c. 多少个表明规则

亚洲必赢官网 11亚洲必赢官网 12

from django.conf.urls import url, include
from web.views.s2_auth import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 13亚洲必赢官网 14

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.request import Request
from rest_framework import exceptions

token_list = [
    'sfsfss123kuf3j123',
    'asijnfowerkkf9812',
]


class Test1Authentication(BaseAuthentication):
    def authenticate(self, request):
        """
        用户认证,如果验证成功后返回元组: (用户,用户Token)
        :param request: 
        :return: 
            None,表示跳过该验证;
                如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                self._authenticator = None
                if api_settings.UNAUTHENTICATED_USER:
                    self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
                else:
                    self.user = None

                if api_settings.UNAUTHENTICATED_TOKEN:
                    self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
                else:
                    self.auth = None
            (user,token)表示验证通过并设置用户名和Token;
            AuthenticationFailed异常
        """
        import base64
        auth = request.META.get('HTTP_AUTHORIZATION', b'')
        if auth:
            auth = auth.encode('utf-8')
        else:
            return None
        print(auth,'xxxx')
        auth = auth.split()
        if not auth or auth[0].lower() != b'basic':
            raise exceptions.AuthenticationFailed('验证失败')
        if len(auth) != 2:
            raise exceptions.AuthenticationFailed('验证失败')
        username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')
        if username == 'alex' and password == '123':
            return ('登录用户', '用户token')
        else:
            raise exceptions.AuthenticationFailed('用户名或密码错误')

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        # return 'Basic realm=api'
        pass

class Test2Authentication(BaseAuthentication):
    def authenticate(self, request):
        """
        用户认证,如果验证成功后返回元组: (用户,用户Token)
        :param request: 
        :return: 
            None,表示跳过该验证;
                如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                self._authenticator = None
                if api_settings.UNAUTHENTICATED_USER:
                    self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
                else:
                    self.user = None

                if api_settings.UNAUTHENTICATED_TOKEN:
                    self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
                else:
                    self.auth = None
            (user,token)表示验证通过并设置用户名和Token;
            AuthenticationFailed异常
        """
        val = request.query_params.get('token')
        if val not in token_list:
            raise exceptions.AuthenticationFailed("用户认证失败")

        return ('登录用户', '用户token')

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        pass


class TestView(APIView):
    authentication_classes = [Test1Authentication, Test2Authentication]
    permission_classes = []

    def get(self, request, *args, **kwargs):
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

d. 认证和权杖

亚洲必赢官网 15亚洲必赢官网 16

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 17亚洲必赢官网 18

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BaseAuthentication
from rest_framework.permissions import BasePermission

from rest_framework.request import Request
from rest_framework import exceptions

token_list = [
    'sfsfss123kuf3j123',
    'asijnfowerkkf9812',
]


class TestAuthentication(BaseAuthentication):
    def authenticate(self, request):
        """
        用户认证,如果验证成功后返回元组: (用户,用户Token)
        :param request: 
        :return: 
            None,表示跳过该验证;
                如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
                self._authenticator = None
                if api_settings.UNAUTHENTICATED_USER:
                    self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
                else:
                    self.user = None

                if api_settings.UNAUTHENTICATED_TOKEN:
                    self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
                else:
                    self.auth = None
            (user,token)表示验证通过并设置用户名和Token;
            AuthenticationFailed异常
        """
        val = request.query_params.get('token')
        if val not in token_list:
            raise exceptions.AuthenticationFailed("用户认证失败")

        return ('登录用户', '用户token')

    def authenticate_header(self, request):
        """
        Return a string to be used as the value of the `WWW-Authenticate`
        header in a `401 Unauthenticated` response, or `None` if the
        authentication scheme should return `403 Permission Denied` responses.
        """
        pass


class TestPermission(BasePermission):
    message = "权限验证失败"

    def has_permission(self, request, view):
        """
        判断是否有权限访问当前请求
        Return `True` if permission is granted, `False` otherwise.
        :param request: 
        :param view: 
        :return: True有权限;False无权限
        """
        if request.user == "管理员":
            return True

    # GenericAPIView中get_object时调用
    def has_object_permission(self, request, view, obj):
        """
        视图继承GenericAPIView,并在其中使用get_object时获取对象时,触发单独对象权限验证
        Return `True` if permission is granted, `False` otherwise.
        :param request: 
        :param view: 
        :param obj: 
        :return: True有权限;False无权限
        """
        if request.user == "管理员":
            return True


class TestView(APIView):
    # 认证的动作是由request.user触发
    authentication_classes = [TestAuthentication, ]

    # 权限
    # 循环执行所有的权限
    permission_classes = [TestPermission, ]

    def get(self, request, *args, **kwargs):
        # self.dispatch
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

e. 全局使用

上述操作中均是对单独视图进行分外安排,即便想要对全局进行布局,则供给再布置文件中写入即可。

亚洲必赢官网 19亚洲必赢官网 20

REST_FRAMEWORK = {
    'UNAUTHENTICATED_USER': None,
    'UNAUTHENTICATED_TOKEN': None,
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "web.utils.TestAuthentication",
    ],
    "DEFAULT_PERMISSION_CLASSES": [
        "web.utils.TestPermission",
    ],
}

settings.py

亚洲必赢官网 21亚洲必赢官网 22

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 23亚洲必赢官网 24

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response

class TestView(APIView):

    def get(self, request, *args, **kwargs):
        # self.dispatch
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

二、restful

4.版本

a. 基于url的get传参方式

如:/users?version=v1

  • settings

    REST_FRAMEWORK = {
        'DEFAULT_VERSION': 'v1',            # 默认版本
        'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
        'VERSION_PARAM': 'version'          # URL中获取值的key
    }
    
  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view(),name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.versioning import QueryParameterVersioning
    
    class TestView(APIView):
        versioning_class = QueryParameterVersioning

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

            # 获取版本
            print(request.version)
            # 获取版本管理的类
            print(request.versioning_scheme)

            # 反向生成URL
            reverse_url = request.versioning_scheme.reverse('test', request=request)
            print(reverse_url)

            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

b. 基于url的正则格局

如:/v1/users/

  • settings.py

    REST_FRAMEWORK = {
        'DEFAULT_VERSION': 'v1',            # 默认版本
        'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
        'VERSION_PARAM': 'version'          # URL中获取值的key
    }
    
  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.versioning import URLPathVersioning
    
    class TestView(APIView):
        versioning_class = URLPathVersioning

        def get(self, request, *args, **kwargs):
            # 获取版本
            print(request.version)
            # 获取版本管理的类
            print(request.versioning_scheme)

            # 反向生成URL
            reverse_url = request.versioning_scheme.reverse('test', request=request)
            print(reverse_url)

            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

c. 基于 accept 请求头格局

如:Accept: application/json; version=1.0

  • settings.py

    REST_FRAMEWORK = {
        'DEFAULT_VERSION': 'v1',            # 默认版本
        'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
        'VERSION_PARAM': 'version'          # URL中获取值的key
    }
    
  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.versioning import AcceptHeaderVersioning
    
    class TestView(APIView):
        versioning_class = AcceptHeaderVersioning

        def get(self, request, *args, **kwargs):
            # 获取版本 HTTP_ACCEPT头
            print(request.version)
            # 获取版本管理的类
            print(request.versioning_scheme)
            # 反向生成URL
            reverse_url = request.versioning_scheme.reverse('test', request=request)
            print(reverse_url)

            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

d. 基于主机名方法

如:v1.example.com

  • settings.py

    ALLOWED_HOSTS = [‘*’]
    REST_FRAMEWORK = {
    ‘DEFAULT_VERSION’: ‘v1’, # 暗许版本
    ‘ALLOWED_VERSIONS’: [‘v1’, ‘v2’], # 允许的版本
    ‘VERSION_PARAM’: ‘version’ # UCRUISERL中得到值的key
    }

  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.versioning import HostNameVersioning
    
    class TestView(APIView):
        versioning_class = HostNameVersioning

        def get(self, request, *args, **kwargs):
            # 获取版本
            print(request.version)
            # 获取版本管理的类
            print(request.versioning_scheme)
            # 反向生成URL
            reverse_url = request.versioning_scheme.reverse('test', request=request)
            print(reverse_url)

            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

e. 基于django路由系统的namespace

如:example.com/v1/users/

    REST_FRAMEWORK = {
        'DEFAULT_VERSION': 'v1',  # 默认版本
        'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
        'VERSION_PARAM': 'version'  # URL中获取值的key
    }
  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^v1/', ([
                          url(r'test/', TestView.as_view(), name='test'),
                      ], None, 'v1')),
        url(r'^v2/', ([
                          url(r'test/', TestView.as_view(), name='test'),
                      ], None, 'v2')),
    
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.versioning import NamespaceVersioning
    
    class TestView(APIView):
        versioning_class = NamespaceVersioning

        def get(self, request, *args, **kwargs):
            # 获取版本
            print(request.version)
            # 获取版本管理的类
            print(request.versioning_scheme)
            # 反向生成URL
            reverse_url = request.versioning_scheme.reverse('test', request=request)
            print(reverse_url)

            return Response('GET请求,响应内容')

        def post(self, request, *args, **kwargs):
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

f. 全局使用

  • settings.py

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

三. 用户访问次数/频率限制

a. 基于用户IP限制访问频率

亚洲必赢官网 25亚洲必赢官网 26

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 27亚洲必赢官网 28

#!/usr/bin/env python
# -*- coding:utf-8 -*-
import time
from rest_framework.views import APIView
from rest_framework.response import Response

from rest_framework import exceptions
from rest_framework.throttling import BaseThrottle
from rest_framework.settings import api_settings

# 保存访问记录
RECORD = {
    '用户IP': [12312139, 12312135, 12312133, ]
}


class TestThrottle(BaseThrottle):
    ctime = time.time

    def get_ident(self, request):
        """
        根据用户IP和代理IP,当做请求者的唯一IP
        Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
        if present and number of proxies is > 0. If not use all of
        HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
        """
        xff = request.META.get('HTTP_X_FORWARDED_FOR')
        remote_addr = request.META.get('REMOTE_ADDR')
        num_proxies = api_settings.NUM_PROXIES

        if num_proxies is not None:
            if num_proxies == 0 or xff is None:
                return remote_addr
            addrs = xff.split(',')
            client_addr = addrs[-min(num_proxies, len(addrs))]
            return client_addr.strip()

        return ''.join(xff.split()) if xff else remote_addr

    def allow_request(self, request, view):
        """
        是否仍然在允许范围内
        Return `True` if the request should be allowed, `False` otherwise.
        :param request: 
        :param view: 
        :return: True,表示可以通过;False表示已超过限制,不允许访问
        """
        # 获取用户唯一标识(如:IP)

        # 允许一分钟访问10次
        num_request = 10
        time_request = 60

        now = self.ctime()
        ident = self.get_ident(request)
        self.ident = ident
        if ident not in RECORD:
            RECORD[ident] = [now, ]
            return True
        history = RECORD[ident]
        while history and history[-1] <= now - time_request:
            history.pop()
        if len(history) < num_request:
            history.insert(0, now)
            return True

    def wait(self):
        """
        多少秒后可以允许继续访问
        Optionally, return a recommended number of seconds to wait before
        the next request.
        """
        last_time = RECORD[self.ident][0]
        now = self.ctime()
        return int(60 + last_time - now)


class TestView(APIView):
    throttle_classes = [TestThrottle, ]

    def get(self, request, *args, **kwargs):
        # self.dispatch
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

    def throttled(self, request, wait):
        """
        访问次数被限制时,定制错误信息
        """

        class Throttled(exceptions.Throttled):
            default_detail = '请求被限制.'
            extra_detail_singular = '请 {wait} 秒之后再重试.'
            extra_detail_plural = '请 {wait} 秒之后再重试.'

        raise Throttled(wait)

views.py

b. 基于用户IP展现访问频率(利于Django缓存)

亚洲必赢官网 29亚洲必赢官网 30

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'test_scope': '10/m',
    },
}

settings.py

亚洲必赢官网 31亚洲必赢官网 32

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 33亚洲必赢官网 34

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response

from rest_framework import exceptions
from rest_framework.throttling import SimpleRateThrottle


class TestThrottle(SimpleRateThrottle):

    # 配置文件定义的显示频率的Key
    scope = "test_scope"

    def get_cache_key(self, request, view):
        """
        Should return a unique cache-key which can be used for throttling.
        Must be overridden.

        May return `None` if the request should not be throttled.
        """
        if not request.user:
            ident = self.get_ident(request)
        else:
            ident = request.user

        return self.cache_format % {
            'scope': self.scope,
            'ident': ident
        }


class TestView(APIView):
    throttle_classes = [TestThrottle, ]

    def get(self, request, *args, **kwargs):
        # self.dispatch
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

    def throttled(self, request, wait):
        """
        访问次数被限制时,定制错误信息
        """

        class Throttled(exceptions.Throttled):
            default_detail = '请求被限制.'
            extra_detail_singular = '请 {wait} 秒之后再重试.'
            extra_detail_plural = '请 {wait} 秒之后再重试.'

        raise Throttled(wait)

views.py

c. view中限制请求频率

亚洲必赢官网 35亚洲必赢官网 36

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'xxxxxx': '10/m',
    },
}

settings.py

亚洲必赢官网 37亚洲必赢官网 38

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 39亚洲必赢官网 40

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response

from rest_framework import exceptions
from rest_framework.throttling import ScopedRateThrottle


# 继承 ScopedRateThrottle
class TestThrottle(ScopedRateThrottle):

    def get_cache_key(self, request, view):
        """
        Should return a unique cache-key which can be used for throttling.
        Must be overridden.

        May return `None` if the request should not be throttled.
        """
        if not request.user:
            ident = self.get_ident(request)
        else:
            ident = request.user

        return self.cache_format % {
            'scope': self.scope,
            'ident': ident
        }


class TestView(APIView):
    throttle_classes = [TestThrottle, ]

    # 在settings中获取 xxxxxx 对应的频率限制值
    throttle_scope = "xxxxxx"

    def get(self, request, *args, **kwargs):
        # self.dispatch
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

    def throttled(self, request, wait):
        """
        访问次数被限制时,定制错误信息
        """

        class Throttled(exceptions.Throttled):
            default_detail = '请求被限制.'
            extra_detail_singular = '请 {wait} 秒之后再重试.'
            extra_detail_plural = '请 {wait} 秒之后再重试.'

        raise Throttled(wait)

views.py

d. 匿名时用IP限制+登录时用Token限制

亚洲必赢官网 41亚洲必赢官网 42

REST_FRAMEWORK = {
    'UNAUTHENTICATED_USER': None,
    'UNAUTHENTICATED_TOKEN': None,
    'DEFAULT_THROTTLE_RATES': {
        'luffy_anon': '10/m',
        'luffy_user': '20/m',
    },
}

settings.py

亚洲必赢官网 43亚洲必赢官网 44

from django.conf.urls import url, include
from web.views.s3_throttling import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view()),
]

urls.py

亚洲必赢官网 45亚洲必赢官网 46

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response

from rest_framework.throttling import SimpleRateThrottle


class LuffyAnonRateThrottle(SimpleRateThrottle):
    """
    匿名用户,根据IP进行限制
    """
    scope = "luffy_anon"

    def get_cache_key(self, request, view):
        # 用户已登录,则跳过 匿名频率限制
        if request.user:
            return None

        return self.cache_format % {
            'scope': self.scope,
            'ident': self.get_ident(request)
        }


class LuffyUserRateThrottle(SimpleRateThrottle):
    """
    登录用户,根据用户token限制
    """
    scope = "luffy_user"

    def get_ident(self, request):
        """
        认证成功时:request.user是用户对象;request.auth是token对象
        :param request: 
        :return: 
        """
        # return request.auth.token
        return "user_token"

    def get_cache_key(self, request, view):
        """
        获取缓存key
        :param request: 
        :param view: 
        :return: 
        """
        # 未登录用户,则跳过 Token限制
        if not request.user:
            return None

        return self.cache_format % {
            'scope': self.scope,
            'ident': self.get_ident(request)
        }


class TestView(APIView):
    throttle_classes = [LuffyUserRateThrottle, LuffyAnonRateThrottle, ]

    def get(self, request, *args, **kwargs):
        # self.dispatch
        print(request.user)
        print(request.auth)
        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

e. 全局使用

亚洲必赢官网 47亚洲必赢官网 48

REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES': [
        'api.utils.throttles.throttles.LuffyAnonRateThrottle',
        'api.utils.throttles.throttles.LuffyUserRateThrottle',
    ],
    'DEFAULT_THROTTLE_RATES': {
        'anon': '10/day',
        'user': '10/day',
        'luffy_anon': '10/m',
        'luffy_user': '20/m',
    },
}

settings

    a、–字面意思:表征状态转移

5.解析器(parser)

依据请求头 content-type 采纳相应的解析器就请求体内容开始展览处理。

a. 仅处理请求头content-type为application/json的请求体

  • urls.py

    from django.conf.urls import url, include
    from web.views.s5_parser import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import JSONParser
    
    class TestView(APIView):
        parser_classes = [JSONParser, ]

        def post(self, request, *args, **kwargs):
            print(request.content_type)

            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)

            # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
            print(request.POST)
            print(request.FILES)

            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

b. 仅处理请求头content-type为application/x-www-form-urlencoded
的请求体

  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import FormParser
    
    class TestView(APIView):
        parser_classes = [FormParser, ]

        def post(self, request, *args, **kwargs):
            print(request.content_type)

            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)

            # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
            print(request.POST)
            print(request.FILES)

            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

c. 仅处理请求头content-type为multipart/form-data的请求体

  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import MultiPartParser
    
    class TestView(APIView):
        parser_classes = [MultiPartParser, ]

        def post(self, request, *args, **kwargs):
            print(request.content_type)

            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
            # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
            print(request.POST)
            print(request.FILES)
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
  • upload.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
        <input type="text" name="user" />
        <input type="file" name="img">
    
        <input type="submit" value="提交">
    
    </form>
    </body>
    </html>
    

d. 仅上传文件

  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import FileUploadParser
    
    class TestView(APIView):
        parser_classes = [FileUploadParser, ]

        def post(self, request, filename, *args, **kwargs):
            print(filename)
            print(request.content_type)

            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
            # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
            print(request.POST)
            print(request.FILES)
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')
  • upload.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
        <input type="text" name="user" />
        <input type="file" name="img">
    
        <input type="submit" value="提交">
    
    </form>
    </body>
    </html>
    

e. 同时多少个Parser

当同时选取多个parser时,rest
framework会依据请求头content-type自动进行比对,并运用对应parser

  • urls.py

        from django.conf.urls import url, include
        from web.views import TestView
    
        urlpatterns = [
            url(r'test/', TestView.as_view(), name='test'),
        ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework.request import Request
    from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
    
    class TestView(APIView):
        parser_classes = [JSONParser, FormParser, MultiPartParser, ]

        def post(self, request, *args, **kwargs):
            print(request.content_type)

            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
            # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
            print(request.POST)
            print(request.FILES)
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

f. 全局使用

  • settings.py

    REST_FRAMEWORK = {
        'DEFAULT_PARSER_CLASSES':[
            'rest_framework.parsers.JSONParser'
            'rest_framework.parsers.FormParser'
            'rest_framework.parsers.MultiPartParser'
        ]
    
    }
    
  • urls.py

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    
    class TestView(APIView):
        def post(self, request, *args, **kwargs):
            print(request.content_type)

            # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data)
            # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
            print(request.POST)
            print(request.FILES)
            return Response('POST请求,响应内容')

        def put(self, request, *args, **kwargs):
            return Response('PUT请求,响应内容')

只顾:个别特殊的值可以通过Django的request对象 request._request
来实行获取

4. 版本

a. 基于url的get传参方式

如:/users?version=v1

亚洲必赢官网 49亚洲必赢官网 50

REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',            # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    'VERSION_PARAM': 'version'          # URL中获取值的key
}

settings.py

亚洲必赢官网 51亚洲必赢官网 52

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view(),name='test'),
]

urls.py

亚洲必赢官网 53亚洲必赢官网 54

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import QueryParameterVersioning


class TestView(APIView):
    versioning_class = QueryParameterVersioning

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

        # 获取版本
        print(request.version)
        # 获取版本管理的类
        print(request.versioning_scheme)

        # 反向生成URL
        reverse_url = request.versioning_scheme.reverse('test', request=request)
        print(reverse_url)

        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

亚洲必赢官网 ,b. 基于url的正则格局

如:/v1/users/

亚洲必赢官网 55亚洲必赢官网 56

REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',            # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    'VERSION_PARAM': 'version'          # URL中获取值的key
}

settings.py

亚洲必赢官网 57亚洲必赢官网 58

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 59亚洲必赢官网 60

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning


class TestView(APIView):
    versioning_class = URLPathVersioning

    def get(self, request, *args, **kwargs):
        # 获取版本
        print(request.version)
        # 获取版本管理的类
        print(request.versioning_scheme)

        # 反向生成URL
        reverse_url = request.versioning_scheme.reverse('test', request=request)
        print(reverse_url)

        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

c. 基于 accept 请求头情势

如:Accept:
application/json; version=1.0

亚洲必赢官网 61亚洲必赢官网 62

REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',            # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    'VERSION_PARAM': 'version'          # URL中获取值的key
}

settings.py

亚洲必赢官网 63亚洲必赢官网 64

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 65亚洲必赢官网 66

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import AcceptHeaderVersioning


class TestView(APIView):
    versioning_class = AcceptHeaderVersioning

    def get(self, request, *args, **kwargs):
        # 获取版本 HTTP_ACCEPT头
        print(request.version)
        # 获取版本管理的类
        print(request.versioning_scheme)
        # 反向生成URL
        reverse_url = request.versioning_scheme.reverse('test', request=request)
        print(reverse_url)

        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

d. 基于主机名方法

如:v1.example.com

亚洲必赢官网 67亚洲必赢官网 68

ALLOWED_HOSTS = ['*']
REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',  # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
    'VERSION_PARAM': 'version'  # URL中获取值的key
}

settings.py

亚洲必赢官网 69亚洲必赢官网 70

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 71亚洲必赢官网 72

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import HostNameVersioning


class TestView(APIView):
    versioning_class = HostNameVersioning

    def get(self, request, *args, **kwargs):
        # 获取版本
        print(request.version)
        # 获取版本管理的类
        print(request.versioning_scheme)
        # 反向生成URL
        reverse_url = request.versioning_scheme.reverse('test', request=request)
        print(reverse_url)

        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

e. 基于django路由系统的namespace

如:example.com/v1/users/

亚洲必赢官网 73亚洲必赢官网 74

REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',  # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
    'VERSION_PARAM': 'version'  # URL中获取值的key
}

settings.py

亚洲必赢官网 75亚洲必赢官网 76

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'^v1/', ([
                      url(r'test/', TestView.as_view(), name='test'),
                  ], None, 'v1')),
    url(r'^v2/', ([
                      url(r'test/', TestView.as_view(), name='test'),
                  ], None, 'v2')),

]

urls.py

亚洲必赢官网 77亚洲必赢官网 78

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.versioning import NamespaceVersioning


class TestView(APIView):
    versioning_class = NamespaceVersioning

    def get(self, request, *args, **kwargs):
        # 获取版本
        print(request.version)
        # 获取版本管理的类
        print(request.versioning_scheme)
        # 反向生成URL
        reverse_url = request.versioning_scheme.reverse('test', request=request)
        print(reverse_url)

        return Response('GET请求,响应内容')

    def post(self, request, *args, **kwargs):
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

f. 全局使用

亚洲必赢官网 79亚洲必赢官网 80

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

settings.py

    b、面向能源编制程序,对互连网上的自由东西都视为财富

6.序列化

体系化用于对用户请求数据开始展览认证和数码开始展览类别化。

a. 自定义字段

  • urls.py

    from django.conf.urls import url, include
    from web.views.s6_serializers import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import serializers
    from .. import models
    
    class PasswordValidator(object):
        def __init__(self, base):
            self.base = base

        def __call__(self, value):
            if value != self.base:
                message = 'This field must be %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 UserSerializer(serializers.Serializer):
        ut_title = serializers.CharField(source='ut.title')
        user = serializers.CharField(min_length=6)
        pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('666')])


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

            # 序列化,将数据库查询字段序列化为字典
            data_list = models.UserInfo.objects.all()
            ser = UserSerializer(instance=data_list, many=True)
            # 或
            # obj = models.UserInfo.objects.all().first()
            # ser = UserSerializer(instance=obj, many=False)
            return Response(ser.data)

        def post(self, request, *args, **kwargs):
            # 验证,对请求发来的数据进行验证
            ser = UserSerializer(data=request.data)
            if ser.is_valid():
                print(ser.validated_data)
            else:
                print(ser.errors)

            return Response('POST请求,响应内容')

b. 基于Model自动生成字段

  • urls.py

    from django.conf.urls import url, include
    from web.views.s6_serializers import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import serializers
    from .. import models
    
    class PasswordValidator(object):
        def __init__(self, base):
            self.base = str(base)

        def __call__(self, value):
            if value != self.base:
                message = 'This field must be %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 ModelUserSerializer(serializers.ModelSerializer):

        user = serializers.CharField(max_length=32)

        class Meta:
            model = models.UserInfo
            fields = "__all__"
            # fields = ['user', 'pwd', 'ut']
            depth = 2
            extra_kwargs = {'user': {'min_length': 6}, 'pwd': {'validators': [PasswordValidator(666), ]}}
            # read_only_fields = ['user']


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

            # 序列化,将数据库查询字段序列化为字典
            data_list = models.UserInfo.objects.all()
            ser = ModelUserSerializer(instance=data_list, many=True)
            # 或
            # obj = models.UserInfo.objects.all().first()
            # ser = UserSerializer(instance=obj, many=False)
            return Response(ser.data)

        def post(self, request, *args, **kwargs):
            # 验证,对请求发来的数据进行验证
            print(request.data)
            ser = ModelUserSerializer(data=request.data)
            if ser.is_valid():
                print(ser.validated_data)
            else:
                print(ser.errors)

            return Response('POST请求,响应内容')

c. 生成URL

  • urls.py

    from django.conf.urls import url, include
    from web.views.s6_serializers import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
        url(r'detail/(?P<pk>\d+)/', TestView.as_view(), name='detail'),
    ]
    
  • views.py

    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView
    from rest_framework.response import Response
    from rest_framework import serializers
    from .. import models
    
    class PasswordValidator(object):
        def __init__(self, base):
            self.base = str(base)

        def __call__(self, value):
            if value != self.base:
                message = 'This field must be %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 ModelUserSerializer(serializers.ModelSerializer):
        ut = serializers.HyperlinkedIdentityField(view_name='detail')
        class Meta:
            model = models.UserInfo
            fields = "__all__"

            extra_kwargs = {
                'user': {'min_length': 6},
                'pwd': {'validators': [PasswordValidator(666),]},
            }



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

            # 序列化,将数据库查询字段序列化为字典
            data_list = models.UserInfo.objects.all()
            ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request})
            # 或
            # obj = models.UserInfo.objects.all().first()
            # ser = UserSerializer(instance=obj, many=False)
            return Response(ser.data)

        def post(self, request, *args, **kwargs):
            # 验证,对请求发来的数据进行验证
            print(request.data)
            ser = ModelUserSerializer(data=request.data)
            if ser.is_valid():
                print(ser.validated_data)
            else:
                print(ser.errors)

            return Response('POST请求,响应内容')

5. 解析器(parser) 

依照请求头 content-type 选取相应的解析器就请求体内容开始展览拍卖。

a. 仅处理请求头content-type为application/json的请求体

亚洲必赢官网 81亚洲必赢官网 82

from django.conf.urls import url, include
from web.views.s5_parser import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 83亚洲必赢官网 84

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser


class TestView(APIView):
    parser_classes = [JSONParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)

        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

b. 仅处理请求头content-type为application/x-www-form-urlencoded 的请求体

亚洲必赢官网 85亚洲必赢官网 86

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 87亚洲必赢官网 88

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FormParser


class TestView(APIView):
    parser_classes = [FormParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)

        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)

        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

c. 仅处理请求头content-type为multipart/form-data的请求体

亚洲必赢官网 89亚洲必赢官网 90

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 91亚洲必赢官网 92

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import MultiPartParser


class TestView(APIView):
    parser_classes = [MultiPartParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

亚洲必赢官网 93亚洲必赢官网 94

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
    <input type="text" name="user" />
    <input type="file" name="img">

    <input type="submit" value="提交">

</form>
</body>
</html>

upload.html

d. 仅上传文件

亚洲必赢官网 95亚洲必赢官网 96

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 97亚洲必赢官网 98

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser


class TestView(APIView):
    parser_classes = [FileUploadParser, ]

    def post(self, request, filename, *args, **kwargs):
        print(filename)
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

亚洲必赢官网 99亚洲必赢官网 100

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
    <input type="text" name="user" />
    <input type="file" name="img">

    <input type="submit" value="提交">

</form>
</body>
</html>

upload.html

e. 同时多少个Parser

当同时选择多个parser时,rest
framework会依照请求头content-type自动举办比对,并使用对应parser

亚洲必赢官网 101亚洲必赢官网 102

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 103亚洲必赢官网 104

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import JSONParser, FormParser, MultiPartParser


class TestView(APIView):
    parser_classes = [JSONParser, FormParser, MultiPartParser, ]

    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

f. 全局使用

亚洲必赢官网 105亚洲必赢官网 106

REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':[
        'rest_framework.parsers.JSONParser'
        'rest_framework.parsers.FormParser'
        'rest_framework.parsers.MultiPartParser'
    ]

}

settings.py

亚洲必赢官网 107亚洲必赢官网 108

from django.conf.urls import url, include
from web.views import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 109亚洲必赢官网 110

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response


class TestView(APIView):
    def post(self, request, *args, **kwargs):
        print(request.content_type)

        # 获取请求的值,并使用对应的JSONParser进行处理
        print(request.data)
        # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
        print(request.POST)
        print(request.FILES)
        return Response('POST请求,响应内容')

    def put(self, request, *args, **kwargs):
        return Response('PUT请求,响应内容')

views.py

留神:个别特殊的值能够经过Django的request对象
request._request 来进行获取

         如:-

6. 序列化

连串化用于对用户请求数据开始展览表达和多少举办类别化。

a. 自定义字段

亚洲必赢官网 111亚洲必赢官网 112

from django.conf.urls import url, include
from web.views.s6_serializers import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 113亚洲必赢官网 114

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from .. import models


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

    def __call__(self, value):
        if value != self.base:
            message = 'This field must be %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 UserSerializer(serializers.Serializer):
    ut_title = serializers.CharField(source='ut.title')
    user = serializers.CharField(min_length=6)
    pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('666')])


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

        # 序列化,将数据库查询字段序列化为字典
        data_list = models.UserInfo.objects.all()
        ser = UserSerializer(instance=data_list, many=True)
        # 或
        # obj = models.UserInfo.objects.all().first()
        # ser = UserSerializer(instance=obj, many=False)
        return Response(ser.data)

    def post(self, request, *args, **kwargs):
        # 验证,对请求发来的数据进行验证
        ser = UserSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)

        return Response('POST请求,响应内容')

views.py

b. 基于Model自动生成字段

亚洲必赢官网 115亚洲必赢官网 116

from django.conf.urls import url, include
from web.views.s6_serializers import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]

urls.py

亚洲必赢官网 117亚洲必赢官网 118

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from .. import models


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

    def __call__(self, value):
        if value != self.base:
            message = 'This field must be %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 ModelUserSerializer(serializers.ModelSerializer):

    user = serializers.CharField(max_length=32)

    class Meta:
        model = models.UserInfo
        fields = "__all__"
        # fields = ['user', 'pwd', 'ut']
        depth = 2
        extra_kwargs = {'user': {'min_length': 6}, 'pwd': {'validators': [PasswordValidator(666), ]}}
        # read_only_fields = ['user']


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

        # 序列化,将数据库查询字段序列化为字典
        data_list = models.UserInfo.objects.all()
        ser = ModelUserSerializer(instance=data_list, many=True)
        # 或
        # obj = models.UserInfo.objects.all().first()
        # ser = UserSerializer(instance=obj, many=False)
        return Response(ser.data)

    def post(self, request, *args, **kwargs):
        # 验证,对请求发来的数据进行验证
        print(request.data)
        ser = ModelUserSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)

        return Response('POST请求,响应内容')

views.py

c. 生成URL

亚洲必赢官网 119亚洲必赢官网 120

from django.conf.urls import url, include
from web.views.s6_serializers import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
    url(r'detail/(?P<pk>\d+)/', TestView.as_view(), name='detail'),
]

urls.py

亚洲必赢官网 121亚洲必赢官网 122

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from .. import models


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

    def __call__(self, value):
        if value != self.base:
            message = 'This field must be %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 ModelUserSerializer(serializers.ModelSerializer):
    ut = serializers.HyperlinkedIdentityField(view_name='detail')
    class Meta:
        model = models.UserInfo
        fields = "__all__"

        extra_kwargs = {
            'user': {'min_length': 6},
            'pwd': {'validators': [PasswordValidator(666),]},
        }



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

        # 序列化,将数据库查询字段序列化为字典
        data_list = models.UserInfo.objects.all()
        ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request})
        # 或
        # obj = models.UserInfo.objects.all().first()
        # ser = UserSerializer(instance=obj, many=False)
        return Response(ser.data)

    def post(self, request, *args, **kwargs):
        # 验证,对请求发来的数据进行验证
        print(request.data)
        ser = ModelUserSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)

        return Response('POST请求,响应内容')

views.py

d. 自动生成UCR-VL

亚洲必赢官网 123亚洲必赢官网 124

from django.conf.urls import url, include
from web.views.s6_serializers import TestView

urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
    url(r'detail/(?P<pk>\d+)/', TestView.as_view(), name='xxxx'),
]

urls.py

亚洲必赢官网 125亚洲必赢官网 126

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from .. import models


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

    def __call__(self, value):
        if value != self.base:
            message = 'This field must be %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 ModelUserSerializer(serializers.HyperlinkedModelSerializer):
    ll = serializers.HyperlinkedIdentityField(view_name='xxxx')
    tt = serializers.CharField(required=False)

    class Meta:
        model = models.UserInfo
        fields = "__all__"
        list_serializer_class = serializers.ListSerializer

        extra_kwargs = {
            'user': {'min_length': 6},
            'pwd': {'validators': [PasswordValidator(666), ]},
            'url': {'view_name': 'xxxx'},
            'ut': {'view_name': 'xxxx'},
        }


class TestView(APIView):
    def get(self, request, *args, **kwargs):
        # # 序列化,将数据库查询字段序列化为字典
        data_list = models.UserInfo.objects.all()
        ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request})
        # # 如果Many=True
        # # 或
        # # obj = models.UserInfo.objects.all().first()
        # # ser = UserSerializer(instance=obj, many=False)
        return Response(ser.data)

    def post(self, request, *args, **kwargs):
        # 验证,对请求发来的数据进行验证
        print(request.data)
        ser = ModelUserSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)

        return Response('POST请求,响应内容')

views.py

                –

7. 分页

a. 根据页码实行分页

亚洲必赢官网 127亚洲必赢官网 128

from django.conf.urls import url, include
from rest_framework import routers
from web.views import s9_pagination

urlpatterns = [
    url(r'^test/', s9_pagination.UserViewSet.as_view()),
]

urs.py

亚洲必赢官网 129亚洲必赢官网 130

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework import serializers
from .. import models

from rest_framework.pagination import PageNumberPagination


class StandardResultsSetPagination(PageNumberPagination):
    # 默认每页显示的数据条数
    page_size = 1
    # 获取URL参数中设置的每页显示数据条数
    page_size_query_param = 'page_size'

    # 获取URL参数中传入的页码key
    page_query_param = 'page'

    # 最大支持的每页显示的数据条数
    max_page_size = 1


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(APIView):
    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all().order_by('-id')

        # 实例化分页对象,获取数据库中的分页数据
        paginator = StandardResultsSetPagination()
        page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)

        # 序列化对象
        serializer = UserSerializer(page_user_list, many=True)

        # 生成分页和数据
        response = paginator.get_paginated_response(serializer.data)
        return response

views.py

b. 地方和个数举办分页

亚洲必赢官网 131亚洲必赢官网 132

from django.conf.urls import url, include
from web.views import s9_pagination

urlpatterns = [
    url(r'^test/', s9_pagination.UserViewSet.as_view()),
]

urls.py

亚洲必赢官网 133亚洲必赢官网 134

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework import serializers
from .. import models

from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination


class StandardResultsSetPagination(LimitOffsetPagination):
    # 默认每页显示的数据条数
    default_limit = 10
    # URL中传入的显示数据条数的参数
    limit_query_param = 'limit'
    # URL中传入的数据位置的参数
    offset_query_param = 'offset'
    # 最大每页显得条数
    max_limit = None

class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(APIView):
    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all().order_by('-id')

        # 实例化分页对象,获取数据库中的分页数据
        paginator = StandardResultsSetPagination()
        page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)

        # 序列化对象
        serializer = UserSerializer(page_user_list, many=True)

        # 生成分页和数据
        response = paginator.get_paginated_response(serializer.data)
        return response

views.py

c. 游标分页

亚洲必赢官网 135亚洲必赢官网 136

from django.conf.urls import url, include
from web.views import s9_pagination

urlpatterns = [
    url(r'^test/', s9_pagination.UserViewSet.as_view()),
]

urls.py

亚洲必赢官网 137亚洲必赢官网 138

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework import serializers
from .. import models

from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination


class StandardResultsSetPagination(CursorPagination):
    # URL传入的游标参数
    cursor_query_param = 'cursor'
    # 默认每页显示的数据条数
    page_size = 2
    # URL传入的每页显示条数的参数
    page_size_query_param = 'page_size'
    # 每页显示数据最大条数
    max_page_size = 1000

    # 根据ID从大到小排列
    ordering = "id"



class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(APIView):
    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all().order_by('-id')

        # 实例化分页对象,获取数据库中的分页数据
        paginator = StandardResultsSetPagination()
        page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)

        # 序列化对象
        serializer = UserSerializer(page_user_list, many=True)

        # 生成分页和数据
        response = paginator.get_paginated_response(serializer.data)
        return response

views.py

三、restful规范

八. 路由系统

a. 自定义路由

亚洲必赢官网 139亚洲必赢官网 140

from django.conf.urls import url, include
from web.views import s11_render

urlpatterns = [
    url(r'^test/$', s11_render.TestView.as_view()),
    url(r'^test\.(?P<format>[a-z0-9]+)$', s11_render.TestView.as_view()),
    url(r'^test/(?P<pk>[^/.]+)/$', s11_render.TestView.as_view()),
    url(r'^test/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)$', s11_render.TestView.as_view())
]

urls.py

亚洲必赢官网 141亚洲必赢官网 142

from rest_framework.views import APIView
from rest_framework.response import Response
from .. import models


class TestView(APIView):
    def get(self, request, *args, **kwargs):
        print(kwargs)
        print(self.renderer_classes)
        return Response('...')

views.py

b. 半自动路由

亚洲必赢官网 143亚洲必赢官网 144

from django.conf.urls import url, include
from web.views import s10_generic

urlpatterns = [
    url(r'^test/$', s10_generic.UserViewSet.as_view({'get': 'list', 'post': 'create'})),
    url(r'^test/(?P<pk>\d+)/$', s10_generic.UserViewSet.as_view(
        {'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]

urls.py

亚洲必赢官网 145亚洲必赢官网 146

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
from .. import models


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(ModelViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer

views.py

c. 全自动路由

亚洲必赢官网 147亚洲必赢官网 148

from django.conf.urls import url, include
from rest_framework import routers
from web.views import s10_generic


router = routers.DefaultRouter()
router.register(r'users', s10_generic.UserViewSet)

urlpatterns = [
    url(r'^', include(router.urls)),
]

urls.py

亚洲必赢官网 149亚洲必赢官网 150

from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
from .. import models


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(ModelViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer

views.py

     a、 —URL

9. 视图

a. GenericViewSet

亚洲必赢官网 151亚洲必赢官网 152

from django.conf.urls import url, include
from web.views.s7_viewset import TestView

urlpatterns = [
    url(r'test/', TestView.as_view({'get':'list'}), name='test'),
    url(r'detail/(?P<pk>\d+)/', TestView.as_view({'get':'list'}), name='xxxx'),
]

urls.py

亚洲必赢官网 153亚洲必赢官网 154

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework import viewsets
from rest_framework.response import Response


class TestView(viewsets.GenericViewSet):
    def list(self, request, *args, **kwargs):
        return Response('...')

    def add(self, request, *args, **kwargs):
        pass

    def delete(self, request, *args, **kwargs):
        pass

    def edit(self, request, *args, **kwargs):
        pass

views.py

b. ModelViewSet(自定义URL)

亚洲必赢官网 155亚洲必赢官网 156

from django.conf.urls import url, include
from web.views import s10_generic

urlpatterns = [
    url(r'^test/$', s10_generic.UserViewSet.as_view({'get': 'list', 'post': 'create'})),
    url(r'^test/(?P<pk>\d+)/$', s10_generic.UserViewSet.as_view(
        {'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]

urls.py

亚洲必赢官网 157亚洲必赢官网 158

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.viewsets import ModelViewSet
from rest_framework import serializers
from .. import models


class UserSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class UserViewSet(ModelViewSet):
    queryset = models.UserInfo.objects.all()
    serializer_class = UserSerializer

views.py

c. ModelViewSet(rest framework路由)

亚洲必赢官网 159亚洲必赢官网 160

from django.conf.urls import url, include
from rest_framework import routers
from app01 import views

router = routers.DefaultRouter()
router.register(r'users', views.UserViewSet)
router.register(r'groups', views.GroupViewSet)

# Wire up our API using automatic URL routing.
# Additionally, we include login URLs for the browsable API.
urlpatterns = [
    url(r'^', include(router.urls)),
]

urls.py

亚洲必赢官网 161亚洲必赢官网 162

from rest_framework import viewsets
from rest_framework import serializers


class UserSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.User
        fields = ('url', 'username', 'email', 'groups')


class GroupSerializer(serializers.HyperlinkedModelSerializer):
    class Meta:
        model = models.Group
        fields = ('url', 'name')

class UserViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows users to be viewed or edited.
    """
    queryset = User.objects.all().order_by('-date_joined')
    serializer_class = UserSerializer


class GroupViewSet(viewsets.ModelViewSet):
    """
    API endpoint that allows groups to be viewed or edited.
    """
    queryset = Group.objects.all()
    serializer_class = GroupSerializer

views.py

     b、 —url名词

10. 渲染器

依照 用户请求UOdysseyL 或
用户可承受的档次,筛选出确切的 渲染组件。
用户请求U本田CR-VL:

  • 用户请求头:

  • Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8

a. json

访问URL:

  •  

亚洲必赢官网 163亚洲必赢官网 164

from django.conf.urls import url, include
from web.views import s11_render

urlpatterns = [
    url(r'^test/$', s11_render.TestView.as_view()),
    url(r'^test\.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()),
]

urls.py

亚洲必赢官网 165亚洲必赢官网 166

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

from rest_framework.renderers import JSONRenderer

from .. import models


class TestSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class TestView(APIView):
    renderer_classes = [JSONRenderer, ]

    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all()
        ser = TestSerializer(instance=user_list, many=True)
        return Response(ser.data)

views.py

b. 表格

访问URL:

  •  

亚洲必赢官网 167亚洲必赢官网 168

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

from rest_framework.renderers import AdminRenderer

from .. import models


class TestSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class TestView(APIView):
    renderer_classes = [AdminRenderer, ]

    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all()
        ser = TestSerializer(instance=user_list, many=True)
        return Response(ser.data)

views.py

c. Form表单

访问URL:

  •  

亚洲必赢官网 169亚洲必赢官网 170

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

from rest_framework.renderers import JSONRenderer
from rest_framework.renderers import AdminRenderer
from rest_framework.renderers import HTMLFormRenderer

from .. import models


class TestSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class TestView(APIView):
    renderer_classes = [HTMLFormRenderer, ]

    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all().first()
        ser = TestSerializer(instance=user_list, many=False)
        return Response(ser.data)

views.py

d. 自定义呈现模板

访问URL:

  •  

亚洲必赢官网 171亚洲必赢官网 172

from django.conf.urls import url, include
from web.views import s11_render

urlpatterns = [
    url(r'^test/$', s11_render.TestView.as_view()),
    url(r'^test\.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()),
]

urls.py

亚洲必赢官网 173亚洲必赢官网 174

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers
from rest_framework.renderers import TemplateHTMLRenderer

from .. import models


class TestSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class TestView(APIView):
    renderer_classes = [TemplateHTMLRenderer, ]

    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all().first()
        ser = TestSerializer(instance=user_list, many=False)
        return Response(ser.data, template_name='user_detail.html')

views.py

亚洲必赢官网 175亚洲必赢官网 176

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
    {{ user }}
    {{ pwd }}
    {{ ut }}
</body>
</html>

userdetail.html

e. 浏览器格式API+JSON

访问URL:

  •  

亚洲必赢官网 177亚洲必赢官网 178

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import serializers

from rest_framework.renderers import JSONRenderer
from rest_framework.renderers import BrowsableAPIRenderer

from .. import models


class TestSerializer(serializers.ModelSerializer):
    class Meta:
        model = models.UserInfo
        fields = "__all__"


class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
    def get_default_renderer(self, view):
        return JSONRenderer()


class TestView(APIView):
    renderer_classes = [CustomBrowsableAPIRenderer, ]

    def get(self, request, *args, **kwargs):
        user_list = models.UserInfo.objects.all().first()
        ser = TestSerializer(instance=user_list, many=False)
        return Response(ser.data, template_name='user_detail.html')

views.py

只顾:假若还要多个设有时,自动依照U帕杰罗L后缀来挑选渲染器。

 

 

 

 

路径,视网络上任何东西都是资源,均使用名词表示(可复数)
  https://api.example.com/v1/zoos
  https://api.example.com/v1/animals
  https://api.example.com/v1/employee

    c、 —status状态码**

200 OK - [GET]:服务器成功返回用户请求的数据,该操作是幂等的(Idempotent)。
201 CREATED - [POST/PUT/PATCH]:用户新建或修改数据成功。
202 Accepted - [*]:表示一个请求已经进入后台排队(异步任务)
204 NO CONTENT - [DELETE]:用户删除数据成功。
400 INVALID REQUEST - [POST/PUT/PATCH]:用户发出的请求有错误,服务器没有进行新建或修改数据的操作,该操作是幂等的。
401 Unauthorized - [*]:表示用户没有权限(令牌、用户名、密码错误)。
403 Forbidden - [*] 表示用户得到授权(与401错误相对),但是访问是被禁止的。
404 NOT FOUND - [*]:用户发出的请求针对的是不存在的记录,服务器没有进行操作,该操作是幂等的。
406 Not Acceptable - [GET]:用户请求的格式不可得(比如用户请求JSON格式,但是只有XML格式)。
410 Gone -[GET]:用户请求的资源被永久删除,且不会再得到的。
422 Unprocesable entity - [POST/PUT/PATCH] 当创建一个对象时,发生一个验证错误。
500 INTERNAL SERVER ERROR - [*]:服务器发生错误,用户将无法判断发出的请求是否成功。

   d、—提交格局

GET      :从服务器取出资源(一项或多项)
POST    :在服务器新建一个资源
PUT      :在服务器更新资源(客户端提供改变后的完整资源)
PATCH  :在服务器更新资源(客户端提供改变的属性)
DELETE :从服务器删除资源

   e、  —错误音信

状态码是4xx时,应返回错误信息,error当做key。
{
    error: "Invalid API key"
}

   f、 —版本**

   g、 —Hypermedia link,RESTful
API最佳实现Hypermedia,即重返结果中提供链接,连向任何API方法,使得用户不查文书档案,也知晓下一步应该做什么。

   h、—域名**

   j、—过滤,通过在url上传参的样式传递搜索条件**

 
k、 
—重返结果,针对分裂操作,服务器向用户重临的结果应该符合以下标准**

GET /collection:返回资源对象的列表(数组)  
GET /collection/resource:返回单个资源对象
POST /collection:返回新生成的资源对象
PUT /collection/resource:返回完整的资源对象
PATCH /collection/resource:返回完整的资源对象
DELETE /collection/resource:返回一个空文档

rest_Framework的规范:

   
按梯次:它的method的不一致,原来未有设想,原来是url区分,今后因此method来区分,method的不如提交格局分裂,紧接着一般是面向能源的就是把url变成名词,接下正是重返值,在此之前未有设想状态码,以往有思虑状态码。(一般有get,post方法,还有put,delete等办法)

**4、 基于Django Rest Framework框架完结 **

   a、安装:pip3 install djangorestframework -i
–trusted-host=pypi.douban.com

五、什么是RESTful

  • REST与技能非亲非故,代表的是一种软件架构风格,REST是Representational
    State Transfer的简称,汉语翻译为“表征状态转移”
  • REST从财富的角度类审视整个互连网,它将分布在网络中有个别节点的财富通过U奇骏L进行标识,客户端应用通过U揽胜L来获取能源的风味,获得那几个特色致使这一个应用转变状态
  • REST与技能毫不相关,代表的是壹种软件架构风格,REST是Representational
    State Transfer的简称,汉语翻译为“表征状态转移”
  • 怀有的数量,可是是通过网络获取的或然操作(增删改查)的数码,都以资源,将一切数据便是财富是REST差别与其它架构风格的最本质属性
  • 对此REST那种面向财富的架构风格,有人提议壹种崭新的结构理念,即:面向能源架构(ROA:Resource
    Oriented Architecture)

      a、 django的中间件比rest_framework执行的早**

      b、 认证的成效放到中间件也是足以做的**

     
c、
证实1般做,检查用户是还是不是存在,要是存在request.user/request.auth;不设有request.user/request.auth=None**

      d、证实验小学总计:**

  ---类:authenticate/authenticate_header

      ---返回值:None,元组(user,auth),异常

      ---配置:

                 ---视图:                      

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

                 ---全局                    

                                    REST_FRAMEWORK = {
                                                'UNAUTHENTICATED_USER': None,
                                                'UNAUTHENTICATED_TOKEN': None,
                                                "DEFAULT_AUTHENTICATION_CLASSES": [
                                                 # "app02.utils.MyAuthentication",
                                                ],
                                               }

六、权限

   
a、
权限才真的的做request.user/request.auth得到它们做是还是不是访问的论断**

    b、权力小总计: **

     ---类:       has_permission/has_object_permission

     ---返回值:True、False、exceptions.PermissionDenied(detail="错误信息")

     ---配置:

               ---视图:                  

                                class IndexView(APIView):
                                       permission_classes = [MyPermission,]

                      ---全局:

                                REST_FRAMEWORK = {
                                "DEFAULT_PERMISSION_CLASSES": [
                                # "app02.utils.MyAuthentication",
                                 ],
                               }

七、限制访问的频率

    限制访问频率的利用:

   a、对匿名用户展开界定,每一个用户一分钟允许访问十三遍

        在那边用唯1标识:self.get_ident() 

   b、范围访问的成效小总括: **

  ---类:       allow_request/wait PS: scope = "wdp_user"

     ---返回值:True、False

     ---配置:

                  ---视图:

                                            class IndexView(APIView):
                                                     throttle_classes=[AnonThrottle,UserThrottle,]
                                                     def get(self,request,*args,**kwargs):
                                                     self.dispatch
                                                     return Response('访问首页')

                   ---全局:

                                          REST_FRAMEWORK = {
                                                      "DEFAULT_THROTTLE_CLASSES":[
                                                   ],
                                                      'DEFAULT_THROTTLE_RATES':{
                                                      'wdp_anon':'5/minute',
                                                      'wdp_user':'10/minute',
                                                   }
                                                   }

、认证、权限、限制访问频率再次来到结果的相比较

    1、证实、权限、限制访问频率这个重回的结果:**

**     a、证实再次来到的两种结果:             a、None             b、元组(user,auth)             c、异常 raise APIException(…)**

**     b、 权限的重回值三种结果:**

**            a、True 有权限             b、False 没权限             c、异常**

**     c、 限制访问的效能再次来到值的三种结果:**

**            a、True 
            b、False**

实例化:
v1 = ["view.xxx.path.Role","view.xxx.path.Group",]    可以循环,循环出来的每一个不能实例化
如果把v1循环弄成每一个对象列表,通过rsplit切割,在通过importlib.import_module拿到每一个路径,在通过getattr把它的类名拿过来,
这个类加括号就是实例化想
for item in v1:
m = importlib.import_module('view.xxx.path')
cls = getattr(m,'Role')
cls()



from view.xxx.path import Role,Group      
v2 = [Group,Role]      这个可以循环每一个实例化
for item in v2:     #循环V2的每一个元素加括号,就是实例化
item()

九、Django rest_Framework框架

     a、  —-为啥用Django rest_Framework框架?**

----首先没有Django rest_Framework框架用django也是可以做出来的,只不过它为我们提供一些API常用的功能,比如:(认证,权限,限流,有了这些我们只需要写个类已配置,
它就能当都市图用,还能全局配置,如果自己写还得写中间件,写装饰器来实现,通过Django rest_Framework框架,他已经把规则写好,只需要写类,只需实现方法,返回值就可以)
实现了一部分功能。

  ----设计比较好

            ----单独视图+全局配置 =>Dajngo中间件(importlib/反射)=>动态配置课扩展(短信,邮件,微信等提醒)

     b、Django rest_Framework原理?

             先起初在路由,路由.as_view,

             点击as_view**

**             恳请进入,走完以上,才走self.dispatch()**

           
 走
self.dispatch()流程如下地址: 

十、版本

**    a、依照url的不及来来操作,版本控制**

**          先在setting中注册**

**十一、rest framework解析器**

**   
a、请求的数码开始展览辨析:请求体进行辨析。表示服务端能够分析的数额格式的类型。**

Content-Type: application/url-encoding.....
            request.body
            request.POST

            Content-Type: application/json.....
            request.body
            request.POST

        客户端:
            Content-Type: application/json
            '{"name":"alex","age":123}'

        服务端接收:
            读取客户端发送的Content-Type的值 application/json

            parser_classes = [JSONParser,]
            media_type_list = ['application/json',]

            如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
            如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据


        配置:
            单视图:
            class UsersView(APIView):
                parser_classes = [JSONParser,]

            全局配置:
                REST_FRAMEWORK = {
                    'VERSION_PARAM':'version',
                    'DEFAULT_VERSION':'v1',
                    'ALLOWED_VERSIONS':['v1','v2'],
                    # 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"
                    'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
                    'DEFAULT_PARSER_CLASSES':[
                        'rest_framework.parsers.JSONParser',
                        'rest_framework.parsers.FormParser',
                    ]
                }

十二、 rest framework序列化+Form

     a、序列化:

               对象 -> 字符串 序列化                字符串 -> 对象 反类别化**

**     b、目的:                消除QuerySet系列化难题**

**十三、怎么要内外端分离**

**    a、因为前端它有协调框架,那样它的作用就那一个高**

**   
b、不做上下端分离,公司只要既有客户端,又有app那种场合下你就的写两回**

**十四、django restful框架好处**

  扶助大家写了无数组件比如:

   
 a、认证:有类,类中的方法
authenticate/authenticate_header,它的再次回到值有None,元组,至极。假若再次来到值为None那就不管,它是匿名用户。**

     b、权限:有类,类中的方法:has_permission**

   
 c、节流:有类,类的不二等秘书籍:allow_request,在这里allow_request来表示限制,它是经过IP来界定,

 它的内部原理是:默认是IP,用户来用IP,这个IP可能代理IP,IP或者是代理IP拿着请求头默认放到大家能够的缓存中                          
去,每一个人的IP为p,后面的那个列表存它的方位时间,每一次请求进来获取它的当前时间根据时间的个数来比较,在                        
比较的过程中看看把不符合时间的个数来进行比较,能访问就继续,不能访问就不要继续。 

   
 d、版本:是url和hostname,他们八个钟每种都有多个章程2个是帮你拿版本另三个是帮你反向生成url

     e、解析器:用户发过来的请求体数据进行操作

     f、系列化:两个成效:连串化,校验

十五、分页

分页的三种情景:

       a、记录当前访问页的多寡id

       b、最多显示120页

       c、对页码进行加密

a、基于limit offset做分页

class P1(LimitOffsetPagination):

                max_limit = 3
                default_limit = 2
                limit_query_param = 'limit'
                offset_query_param = 'offset'


            class IndexView(views.APIView):
                def get(self,request,*args,**kwargs):
                    user_list = models.UserInfo.objects.all()
                    p1 = P1()
                    page_user_list = p1.paginate_queryset(queryset=user_list, request=request, view=self)
                    ser = IndexSerializer(instance=page_user_list, many=True)
                    return Response(ser.data) # 不含上一页和下一页
                    # return p1.get_paginated_response(ser.data) # 含上一页和下一页

            class IndexView(views.APIView):
                def get(self,request,*args,**kwargs):
                    ret = BaseResponse()
                    try:
                        user_list = models.UserInfo.objects.all()
                        p1 = P1()
                        page_user_list = p1.paginate_queryset(queryset=user_list,request=request,view=self)
                        ser = IndexSerializer(instance=page_user_list,many=True)
                        ret.data = ser.data
                        ret.next = p1.get_next_link()
                    except Exception as e:
                        ret.code= 1001
                        ret.error = 'xxxx错误'
                    return Response(ret.__dict__)

 b. 基于页码的分页

class P2(PageNumberPagination):
                # 每页显示的数据条数
                max_page_size = 5
                page_size = 2
                page_size_query_param = 'size'

                # 页码
                page_query_param = 'page'

十六、视图

1、APIView

class IndexView(views.APIView):
                    def get(self, request, *args, **kwargs):
                        user_list = models.UserInfo.objects.all()
                        ser = IndexSerializer(instance=user_list,many=True)
                        return Response(ser.data)

2、GenericAPIview(APIView)

3、GenericViewSet(ViewSetMixin,generics.GenericAPIView)

路由修改:
                    urlpatterns = [
                        url(r'^index/$', views.IndexView.as_view({'get':'list','post':'create'})),
                        url(r'^index/(?P<pk>\d+)$', views.IndexView.as_view({'get':'retrieve'})),
                    ]

                视图修改:

                    class IndexView(viewsets.GenericViewSet):

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

                             pass # 获取列表信息

                        def retrieve(self, request, *args, **kwargs):
                            pass  # 获取单条数据

                        def create(self,request, *args, **kwargs):
                            pass


                自定义:

                        增
                            POST
                            /users/
                        删
                            DELETE
                            /users/1/
                        改
                            PUT
                            /users/1/

                            patch
                            /users/1/
                        查
                            GET
                            /users/ 
                            GET
                            /users/1/

                        urlpatterns = [

                            url(r'^index/$', views.IndexView.as_view()),
                            url(r'^index/(?P<pk>\d+)$', views.IndexView.as_view()),
                        ]

                        class IndexView(views.APIView):

                            def get(self,request,*args,**kwargs):
                                pk = kwargs.get('pk')
                                if pk:
                                    pass # 获取单条信息
                                else:
                                    pass # 获取列表信息

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

                            def put(self,request,*args,**kwargs):
                                pass

                            def patch(self,request,*args,**kwargs):
                                pass

                            def delete(self,request,*args,**kwargs):
                                pass

4、ModelViewSet

ModelViewSet(mixins.CreateModelMixin,mixins.RetrieveModelMixin,mixins.UpdateModelMixin,mixins.DestroyModelMixin,mixins.ListModelMixin,GenericViewSet)                

                class IndexView(ModelViewSet):

十七、 渲染器
    看到的页面时怎么体统的,重临数据。
    renderer_classes = [JSONRenderer,BrowsableAPIRenderer]

十八、跨域

   a、  浏览器的同源策略

              1、  —-对ajax请求进行拦阻

               二、 —-对href属性读不阻拦

       xhr=new XMLHttpRequest

       xhr.open…

       xhr.send(…)

    b、 消除方案:

         —JSONP

                 点击按钮: 

                        动态增加2个

<script src='http://www.baidu.com/users/'></script>
                        <script>
                            function func(arg){
                                alert(arg)
                            }
                        </script

    c、删除

<script src='http://www.baidu.com/users/'></script>

 

1. 跨域
       浏览器的同源策略
            - 对ajax请求进行阻拦
            - 对href属性都不阻拦

        xhr = new XMLHttpRequest();
        xhr.open...
        xhr.send(...)

       解决方案:
            - JSONP
                点击按钮:
                    动态添加一个
                        <script src='http://www.baidu.com/users/'></script>
                        <script>
                            function func(arg){
                                alert(arg)
                            }
                        </script>
                    删除 
                        <script src='http://www.baidu.com/users/'></script>
                PS: 必问

                客户端浏览器:
                    - jsonp(pythonav)

                Pythondv网站-政府:
                    - jsonp(pythonav)

                Pythonav网站:
                    - {
                            'code':1111,
                            'list':[
                                ...
                                ...
                                ...
                            ]

                        }

            - CORS
                客户端浏览器:
                    - $.ajax(pythonav)

                Pythondv网站-政府:
                    - $.ajax(pythonav)

                Pythonav网站:
                    - {
                            'code':1111,
                            'list':[
                                ...
                                ...
                                ...
                            ]

                        }
                    - 响应头

        a. 简单请求(非常好)

            A网站:
                <input type="button" value="获取用户数据" onclick="getUsers()">

                <script src="jquery-1.12.4.min.js"></script>
                <script>
                    function getUsers() {
                        $.ajax({
                            url: 'http://127.0.0.1:8000/users/',
                            type:'GET',
                            success:function (ret) {
                                console.log(ret)
                            }
                        })
                    }
                </script>

            服务商:
                class UsersView(views.APIView):
                    def get(self,request,*args,**kwargs):

                        ret = {
                            'code':1000,
                            'data':'老男孩'
                        }
                        response = JsonResponse(ret)
                        response['Access-Control-Allow-Origin'] = "*"
                        return response

        b. 复杂请求(性能上的损耗,options预检,真实的请求)
            A网站:
                <input type="button" value="获取用户数据" onclick="getUsers()">

                <script src="jquery-1.12.4.min.js"></script>
                <script>
                    function getUsers() {
                        $.ajax({
                            url: 'http://127.0.0.1:8000/users/',
                            type:'POST',
                            data: {'k1':'v1'},
                            headers:{
                                'h1':'asdfasdfasdf'
                            },
                            success:function (ret) {
                                console.log(ret)
                            }
                        })
                    }
                </script>

            服务商:

                class UsersView(views.APIView):
                    def get(self,request,*args,**kwargs):

                        ret = {
                            'code':1000,
                            'data':'老男孩'
                        }
                        response = JsonResponse(ret)
                        response['Access-Control-Allow-Origin'] = "*"
                        return response

                    def post(self,request,*args,**kwargs):
                        print(request.POST)
                        ret = {
                            'code':1000,
                            'data':'老男孩'
                        }
                        response = JsonResponse(ret)
                        response['Access-Control-Allow-Origin'] = "*"
                        return response

                    def options(self, request, *args, **kwargs):
                        # self.set_header('Access-Control-Allow-Origin', "http://www.xxx.com")
                        # self.set_header('Access-Control-Allow-Headers', "k1,k2")
                        # self.set_header('Access-Control-Allow-Methods', "PUT,DELETE")
                        # self.set_header('Access-Control-Max-Age', 10)

                        response = HttpResponse()
                        response['Access-Control-Allow-Origin'] = '*'
                        response['Access-Control-Allow-Headers'] = 'h1'
                        # response['Access-Control-Allow-Methods'] = 'PUT'
                        return response

    2. Vue+rest示例

        前端:vue
            修改源:
                npm config set registry https://registry.npm.taobao.org 

            创建脚手架:
                vue init webpack Vue项目名称
                # Install vue-router? Yes


            插件:
                axios,发送Ajax请求
                vuex,保存所有组件共用的变量
                vue-cookies,操作cookie


        流程:
            1. 创建脚手架 

            2. 
                # 用于点击查看组件
                <router-link to="/index">首页</router-link>

                # 组件显示的位置
                <router-view/>

            3. 写路由
                    import Vue from 'vue'
                    import Router from 'vue-router'
                    import Index from '@/components/Index'
                    import Login from '@/components/Login'
                    import Course from '@/components/Course'
                    import Micro from '@/components/Micro'
                    import News from '@/components/News'
                    import CourseDetail from '@/components/CourseDetail'
                    import NotFound from '@/components/NotFound'

                    Vue.use(Router)

                    export default new Router({
                      routes: [
                        {
                          path: '/',
                          name: 'index',
                          component: Index
                        },
                        {
                          path: '/index',
                          name: 'index',
                          component: Index
                        },
                        {
                          path: '/course',
                          name: 'course',
                          component: Course
                        },
                        {
                          path: '/course-detail/:id/',
                          name: 'courseDetail',
                          component: CourseDetail
                        },
                        {
                          path: '/micro',
                          name: 'micro',
                          component: Micro
                        },
                        {
                          path: '/news',
                          name: 'news',
                          component: News
                        },
                        {
                          path: '/login',
                          name: 'login',
                          component: Login
                        },
                        {
                          path: '*',
                          component: NotFound
                        }
                      ],
                      mode: 'history'
                    })

            4. 写组件
                <template>

                  <div>
                    <h1>登录页面</h1>
                    <div>
                      <input type="text" v-model="username" placeholder="用户名">
                      <input type="text" v-model="password" placeholder="密码">
                      <a @click="doLogin">提交</a>
                    </div>
                  </div>
                </template>

                <script>

                export default {
                  # 定义局部字段
                  data () {
                    return {
                      username: '',
                      password: ''
                    }
                  },
                  # 加载时执行
                  mounted:function(){
                  },
                  # 定义局部方法
                  methods:{
                    doLogin() {
                      var that = this
                      this.$axios.request({
                        url: 'http://127.0.0.1:8000/login/',
                        method: 'POST',
                        data: {
                          username: this.username,
                          password: this.password
                        },
                        responseType: 'json'
                      }).then(function (response) {
                        console.log(response.data)
                        // 找到全局变量,把用户名和token赋值到其中。
                        that.$store.commit('saveToken',response.data)
                        // 重定向到index
                        that.$router.push('/index')
                      })
                    }
                  }
                }
                </script>

                <!-- Add "scoped" attribute to limit CSS to this component only -->
                <style scoped>

                </style>

            5. ajax请求:axios
                npm install axios

                main.js 
                    import Vue from 'vue'
                    import App from './App'
                    import router from './router'

                    import axios from 'axios'

                    Vue.prototype.$axios = axios

                    Vue.config.productionTip = false
                    ...

                组件使用:
                    this.$axios.request({
                    url: 'http://127.0.0.1:8000/login/',
                    method: 'POST',
                    data: {
                      username: this.username,
                      password: this.password
                    },
                    responseType: 'json'
                  }).then(function (response) {
                    console.log(response.data)

                    that.$router.push('/index')
                  })

                PS:重定向 that.$router.push('/index')

            6. vuex 
                npm install vuex 

                main.js 
                    import Vue from 'vue'
                    import App from './App'
                    import router from './router'
                    import axios from 'axios'

                    import store from './store/store'    # vuex

                    Vue.prototype.$axios = axios

                    Vue.config.productionTip = false

                    /* eslint-disable no-new */
                    new Vue({
                      el: '#app',
                      store,                            # vuex
                      router,
                      components: { App },
                      template: '<App/>'
                    })

                src/store/store.js
                    import Vue from 'vue'
                    import Vuex from 'vuex'
                    import Cookie from 'vue-cookies'

                    Vue.use(Vuex)

                    export default new Vuex.Store({
                      // 组件中通过 this.$store.state.username 调用
                      state: {
                        username: Cookie.get('username'),
                        token: Cookie.get('token')
                      },
                      mutations: {
                        // 组件中通过 this.$store.commit(参数)  调用
                        saveToken: function (state, data) {
                          state.username = data.username
                          state.token = data.token
                          Cookie.set('username', data.username, '20min')
                          Cookie.set('token', data.token, '20min')

                        },
                        clearToken: function (state) {
                          state.username = null
                          state.token = null
                          Cookie.remove('username')
                          Cookie.remove('token')
                        }
                      }
                    })

            7. vue-cookies 
                npm install vue-cookies 


                    Cookie.get('username')

                    Cookie.set('username', data.username, '20min')
                    Cookie.remove('username')


                src/store/store.js
                    import Vue from 'vue'
                    import Vuex from 'vuex'
                    import Cookie from 'vue-cookies'    # vue-cookies

                    Vue.use(Vuex)

                    export default new Vuex.Store({
                      // 组件中通过 this.$store.state.username 调用
                      state: {
                        username: Cookie.get('username'),    # vue-cookies
                        token: Cookie.get('token')            # vue-cookies
                      },
                      mutations: {
                        // 组件中通过 this.$store.commit(参数)  调用
                        saveToken: function (state, data) {
                          state.username = data.username
                          state.token = data.token
                          Cookie.set('username', data.username, '20min')    # vue-cookies
                          Cookie.set('token', data.token, '20min')    

                        },
                        clearToken: function (state) {
                          state.username = null
                          state.token = null
                          Cookie.remove('username')    # vue-cookies
                          Cookie.remove('token')
                        }
                      }
                    })

            8. 路由 
                # 定义路由
                    {
                      path: '/course-detail/:id/',
                      name: 'courseDetail',
                      component: CourseDetail
                    },
                    {
                      path: '/login',
                      name: 'login',
                      component: Login
                    },
                    {
                      path: '*',
                      component: NotFound
                    }


                # router-link参数
                    <router-link :to="{'path':'/course-detail/'+item.id }">{{item.name}}</router-link>
                    <router-link to="/index">首页</router-link>

                # 获取传过来的参数
                    this.$route.params.id
                # 重定向
                    this.$router.push('/index')

 

网站地图xml地图