zoukankan      html  css  js  c++  java
  • Django之Rest Framework框架

    一、什么是RESTful

    • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
    • REST从资源的角度类审视整个网络,它将分布在网络中某个节点的资源通过URL进行标识,客户端应用通过URL来获取资源的表征,获得这些表征致使这些应用转变状态
    • REST与技术无关,代表的是一种软件架构风格,REST是Representational State Transfer的简称,中文翻译为“表征状态转移”
    • 所有的数据,不过是通过网络获取的还是操作(增删改查)的数据,都是资源,将一切数据视为资源是REST区别与其他架构风格的最本质属性
    • 对于REST这种面向资源的架构风格,有人提出一种全新的结构理念,即:面向资源架构(ROA:Resource Oriented Architecture)

    二、RESTful API设计

    • API与用户的通信协议,总是使用HTTPs协议
    • 域名 
      • https://api.example.com                         尽量将API部署在专用域名(会存在跨域问题)
      • https://example.org/api/                        API很简单
    • 版本
      • URL,如:https://api.example.com/v1/
      • 请求头                                                  跨域时,引发发送多次请求
    • 路径,视网络上任何东西都是资源,均使用名词表示(可复数)
      • https://api.example.com/v1/zoos
      • https://api.example.com/v1/animals
      • https://api.example.com/v1/employees
    • method
      • GET      :从服务器取出资源(一项或多项)
      • POST    :在服务器新建一个资源
      • PUT      :在服务器更新资源(客户端提供改变后的完整资源)
      • PATCH  :在服务器更新资源(客户端提供改变的属性)
      • DELETE :从服务器删除资源
    • 过滤,通过在url上传参的形式传递搜索条件
      • https://api.example.com/v1/zoos?limit=10:指定返回记录的数量
      • https://api.example.com/v1/zoos?offset=10:指定返回记录的开始位置
      • https://api.example.com/v1/zoos?page=2&per_page=100:指定第几页,以及每页的记录数
      • https://api.example.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
      • https://api.example.com/v1/zoos?animal_type_id=1:指定筛选条件
    • 状态码
    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"
    }}
    

      摘自:http://www.ruanyifeng.com/blog/2014/05/restful_api.html 

    三、基于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) 

     四、基于Django Rest Framework框架实现

    4.1基本流程

    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.2认证和授权

    1、用户url传入的token认证

    url.py

    from django.conf.urls import url, include
    from web.viewsimport TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
     1 from rest_framework.views import APIView
     2 from rest_framework.response import Response
     3 from rest_framework.authentication import BaseAuthentication
     4 from rest_framework.request import Request
     5 from rest_framework import exceptions
     6 
     7 token_list = [
     8     'sfsfss123kuf3j123',
     9     'asijnfowerkkf9812',
    10 ]
    11 
    12 
    13 class TestAuthentication(BaseAuthentication):
    14     def authenticate(self, request):
    15         """
    16         用户认证,如果验证成功后返回元组: (用户,用户Token)
    17         :param request: 
    18         :return: 
    19             None,表示跳过该验证;
    20                 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
    21                 self._authenticator = None
    22                 if api_settings.UNAUTHENTICATED_USER:
    23                     self.user = api_settings.UNAUTHENTICATED_USER()
    24                 else:
    25                     self.user = None
    26         
    27                 if api_settings.UNAUTHENTICATED_TOKEN:
    28                     self.auth = api_settings.UNAUTHENTICATED_TOKEN()
    29                 else:
    30                     self.auth = None
    31             (user,token)表示验证通过并设置用户名和Token;
    32             AuthenticationFailed异常
    33         """
    34         val = request.query_params.get('token')
    35         if val not in token_list:
    36             raise exceptions.AuthenticationFailed("用户认证失败")
    37 
    38         return ('登录用户', '用户token')
    39 
    40     def authenticate_header(self, request):
    41         """
    42         Return a string to be used as the value of the `WWW-Authenticate`
    43         header in a `401 Unauthenticated` response, or `None` if the
    44         authentication scheme should return `403 Permission Denied` responses.
    45         """
    46         # 验证失败时,返回的响应头WWW-Authenticate对应的值
    47         pass
    48 
    49 
    50 class TestView(APIView):
    51     authentication_classes = [TestAuthentication, ]
    52     permission_classes = []
    53 
    54     def get(self, request, *args, **kwargs):
    55         print(request.user)
    56         print(request.auth)
    57         return Response('GET请求,响应内容')
    58 
    59     def post(self, request, *args, **kwargs):
    60         return Response('POST请求,响应内容')
    61 
    62     def put(self, request, *args, **kwargs):
    63         return Response('PUT请求,响应内容')
    views.py

    2、请求头认证

    1 from django.conf.urls import url, include
    2 from web.viewsimport TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view()),
    6 ]
    url.py
     1 from rest_framework.views import APIView
     2 from rest_framework.response import Response
     3 from rest_framework.authentication import BaseAuthentication
     4 from rest_framework.request import Request
     5 from rest_framework import exceptions
     6 
     7 token_list = [
     8     'sfsfss123kuf3j123',
     9     'asijnfowerkkf9812',
    10 ]
    11 
    12 
    13 class TestAuthentication(BaseAuthentication):
    14     def authenticate(self, request):
    15         """
    16         用户认证,如果验证成功后返回元组: (用户,用户Token)
    17         :param request: 
    18         :return: 
    19             None,表示跳过该验证;
    20                 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
    21                 self._authenticator = None
    22                 if api_settings.UNAUTHENTICATED_USER:
    23                     self.user = api_settings.UNAUTHENTICATED_USER()
    24                 else:
    25                     self.user = None
    26         
    27                 if api_settings.UNAUTHENTICATED_TOKEN:
    28                     self.auth = api_settings.UNAUTHENTICATED_TOKEN()
    29                 else:
    30                     self.auth = None
    31             (user,token)表示验证通过并设置用户名和Token;
    32             AuthenticationFailed异常
    33         """
    34         import base64
    35         auth = request.META.get('HTTP_AUTHORIZATION', b'')
    36         if auth:
    37             auth = auth.encode('utf-8')
    38         auth = auth.split()
    39         if not auth or auth[0].lower() != b'basic':
    40             raise exceptions.AuthenticationFailed('验证失败')
    41         if len(auth) != 2:
    42             raise exceptions.AuthenticationFailed('验证失败')
    43         username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')
    44         if username == 'alex' and password == '123':
    45             return ('登录用户', '用户token')
    46         else:
    47             raise exceptions.AuthenticationFailed('用户名或密码错误')
    48 
    49     def authenticate_header(self, request):
    50         """
    51         Return a string to be used as the value of the `WWW-Authenticate`
    52         header in a `401 Unauthenticated` response, or `None` if the
    53         authentication scheme should return `403 Permission Denied` responses.
    54         """
    55         return 'Basic realm=api'
    56 
    57 
    58 class TestView(APIView):
    59     authentication_classes = [TestAuthentication, ]
    60     permission_classes = []
    61 
    62     def get(self, request, *args, **kwargs):
    63         print(request.user)
    64         print(request.auth)
    65         return Response('GET请求,响应内容')
    66 
    67     def post(self, request, *args, **kwargs):
    68         return Response('POST请求,响应内容')
    69 
    70     def put(self, request, *args, **kwargs):
    71         return Response('PUT请求,响应内容')
    views.py

    3、多个认证规则

    1 from django.conf.urls import url, include
    2 from web.views.s2_auth import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view()),
    6 ]
    urls.py
      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 from rest_framework.views import APIView
      4 from rest_framework.response import Response
      5 from rest_framework.authentication import BaseAuthentication
      6 from rest_framework.request import Request
      7 from rest_framework import exceptions
      8 
      9 token_list = [
     10     'sfsfss123kuf3j123',
     11     'asijnfowerkkf9812',
     12 ]
     13 
     14 
     15 class Test1Authentication(BaseAuthentication):
     16     def authenticate(self, request):
     17         """
     18         用户认证,如果验证成功后返回元组: (用户,用户Token)
     19         :param request: 
     20         :return: 
     21             None,表示跳过该验证;
     22                 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
     23                 self._authenticator = None
     24                 if api_settings.UNAUTHENTICATED_USER:
     25                     self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
     26                 else:
     27                     self.user = None
     28 
     29                 if api_settings.UNAUTHENTICATED_TOKEN:
     30                     self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
     31                 else:
     32                     self.auth = None
     33             (user,token)表示验证通过并设置用户名和Token;
     34             AuthenticationFailed异常
     35         """
     36         import base64
     37         auth = request.META.get('HTTP_AUTHORIZATION', b'')
     38         if auth:
     39             auth = auth.encode('utf-8')
     40         else:
     41             return None
     42         print(auth,'xxxx')
     43         auth = auth.split()
     44         if not auth or auth[0].lower() != b'basic':
     45             raise exceptions.AuthenticationFailed('验证失败')
     46         if len(auth) != 2:
     47             raise exceptions.AuthenticationFailed('验证失败')
     48         username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':')
     49         if username == 'alex' and password == '123':
     50             return ('登录用户', '用户token')
     51         else:
     52             raise exceptions.AuthenticationFailed('用户名或密码错误')
     53 
     54     def authenticate_header(self, request):
     55         """
     56         Return a string to be used as the value of the `WWW-Authenticate`
     57         header in a `401 Unauthenticated` response, or `None` if the
     58         authentication scheme should return `403 Permission Denied` responses.
     59         """
     60         # return 'Basic realm=api'
     61         pass
     62 
     63 class Test2Authentication(BaseAuthentication):
     64     def authenticate(self, request):
     65         """
     66         用户认证,如果验证成功后返回元组: (用户,用户Token)
     67         :param request: 
     68         :return: 
     69             None,表示跳过该验证;
     70                 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
     71                 self._authenticator = None
     72                 if api_settings.UNAUTHENTICATED_USER:
     73                     self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
     74                 else:
     75                     self.user = None
     76         
     77                 if api_settings.UNAUTHENTICATED_TOKEN:
     78                     self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
     79                 else:
     80                     self.auth = None
     81             (user,token)表示验证通过并设置用户名和Token;
     82             AuthenticationFailed异常
     83         """
     84         val = request.query_params.get('token')
     85         if val not in token_list:
     86             raise exceptions.AuthenticationFailed("用户认证失败")
     87 
     88         return ('登录用户', '用户token')
     89 
     90     def authenticate_header(self, request):
     91         """
     92         Return a string to be used as the value of the `WWW-Authenticate`
     93         header in a `401 Unauthenticated` response, or `None` if the
     94         authentication scheme should return `403 Permission Denied` responses.
     95         """
     96         pass
     97 
     98 
     99 class TestView(APIView):
    100     authentication_classes = [Test1Authentication, Test2Authentication]
    101     permission_classes = []
    102 
    103     def get(self, request, *args, **kwargs):
    104         print(request.user)
    105         print(request.auth)
    106         return Response('GET请求,响应内容')
    107 
    108     def post(self, request, *args, **kwargs):
    109         return Response('POST请求,响应内容')
    110 
    111     def put(self, request, *args, **kwargs):
    112         return Response('PUT请求,响应内容')
    views.py

    4、认证和权限

    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view()),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.authentication import BaseAuthentication
     6 from rest_framework.permissions import BasePermission
     7 
     8 from rest_framework.request import Request
     9 from rest_framework import exceptions
    10 
    11 token_list = [
    12     'sfsfss123kuf3j123',
    13     'asijnfowerkkf9812',
    14 ]
    15 
    16 
    17 class TestAuthentication(BaseAuthentication):
    18     def authenticate(self, request):
    19         """
    20         用户认证,如果验证成功后返回元组: (用户,用户Token)
    21         :param request: 
    22         :return: 
    23             None,表示跳过该验证;
    24                 如果跳过了所有认证,默认用户和Token和使用配置文件进行设置
    25                 self._authenticator = None
    26                 if api_settings.UNAUTHENTICATED_USER:
    27                     self.user = api_settings.UNAUTHENTICATED_USER() # 默认值为:匿名用户
    28                 else:
    29                     self.user = None
    30         
    31                 if api_settings.UNAUTHENTICATED_TOKEN:
    32                     self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:None
    33                 else:
    34                     self.auth = None
    35             (user,token)表示验证通过并设置用户名和Token;
    36             AuthenticationFailed异常
    37         """
    38         val = request.query_params.get('token')
    39         if val not in token_list:
    40             raise exceptions.AuthenticationFailed("用户认证失败")
    41 
    42         return ('登录用户', '用户token')
    43 
    44     def authenticate_header(self, request):
    45         """
    46         Return a string to be used as the value of the `WWW-Authenticate`
    47         header in a `401 Unauthenticated` response, or `None` if the
    48         authentication scheme should return `403 Permission Denied` responses.
    49         """
    50         pass
    51 
    52 
    53 class TestPermission(BasePermission):
    54     message = "权限验证失败"
    55 
    56     def has_permission(self, request, view):
    57         """
    58         判断是否有权限访问当前请求
    59         Return `True` if permission is granted, `False` otherwise.
    60         :param request: 
    61         :param view: 
    62         :return: True有权限;False无权限
    63         """
    64         if request.user == "管理员":
    65             return True
    66 
    67     # GenericAPIView中get_object时调用
    68     def has_object_permission(self, request, view, obj):
    69         """
    70         视图继承GenericAPIView,并在其中使用get_object时获取对象时,触发单独对象权限验证
    71         Return `True` if permission is granted, `False` otherwise.
    72         :param request: 
    73         :param view: 
    74         :param obj: 
    75         :return: True有权限;False无权限
    76         """
    77         if request.user == "管理员":
    78             return True
    79 
    80 
    81 class TestView(APIView):
    82     # 认证的动作是由request.user触发
    83     authentication_classes = [TestAuthentication, ]
    84 
    85     # 权限
    86     # 循环执行所有的权限
    87     permission_classes = [TestPermission, ]
    88 
    89     def get(self, request, *args, **kwargs):
    90         # self.dispatch
    91         print(request.user)
    92         print(request.auth)
    93         return Response('GET请求,响应内容')
    94 
    95     def post(self, request, *args, **kwargs):
    96         return Response('POST请求,响应内容')
    97 
    98     def put(self, request, *args, **kwargs):
    99         return Response('PUT请求,响应内容')
    views.py

    5、全局使用

    上述操作中均是对单独视图进行特殊配置,如果想要对全局进行配置,则需要再配置文件中写入即可。

     1 REST_FRAMEWORK = {
     2     'UNAUTHENTICATED_USER': None,
     3     'UNAUTHENTICATED_TOKEN': None,
     4     "DEFAULT_AUTHENTICATION_CLASSES": [
     5         "web.utils.TestAuthentication",
     6     ],
     7     "DEFAULT_PERMISSION_CLASSES": [
     8         "web.utils.TestPermission",
     9     ],
    10 }
    settings
    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view()),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 
     6 class TestView(APIView):
     7 
     8     def get(self, request, *args, **kwargs):
     9         # self.dispatch
    10         print(request.user)
    11         print(request.auth)
    12         return Response('GET请求,响应内容')
    13 
    14     def post(self, request, *args, **kwargs):
    15         return Response('POST请求,响应内容')
    16 
    17     def put(self, request, *args, **kwargs):
    18         return Response('PUT请求,响应内容')
    views.py

    4.3用户访问次数/频率限制

    1、基于用户IP限制访问频率

    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view()),
    6 ]
    urls.py
      1 #!/usr/bin/env python
      2 # -*- coding:utf-8 -*-
      3 import time
      4 from rest_framework.views import APIView
      5 from rest_framework.response import Response
      6 
      7 from rest_framework import exceptions
      8 from rest_framework.throttling import BaseThrottle
      9 from rest_framework.settings import api_settings
     10 
     11 # 保存访问记录
     12 RECORD = {
     13     '用户IP': [12312139, 12312135, 12312133, ]
     14 }
     15 
     16 
     17 class TestThrottle(BaseThrottle):
     18     ctime = time.time
     19 
     20     def get_ident(self, request):
     21         """
     22         根据用户IP和代理IP,当做请求者的唯一IP
     23         Identify the machine making the request by parsing HTTP_X_FORWARDED_FOR
     24         if present and number of proxies is > 0. If not use all of
     25         HTTP_X_FORWARDED_FOR if it is available, if not use REMOTE_ADDR.
     26         """
     27         xff = request.META.get('HTTP_X_FORWARDED_FOR')
     28         remote_addr = request.META.get('REMOTE_ADDR')
     29         num_proxies = api_settings.NUM_PROXIES
     30 
     31         if num_proxies is not None:
     32             if num_proxies == 0 or xff is None:
     33                 return remote_addr
     34             addrs = xff.split(',')
     35             client_addr = addrs[-min(num_proxies, len(addrs))]
     36             return client_addr.strip()
     37 
     38         return ''.join(xff.split()) if xff else remote_addr
     39 
     40     def allow_request(self, request, view):
     41         """
     42         是否仍然在允许范围内
     43         Return `True` if the request should be allowed, `False` otherwise.
     44         :param request: 
     45         :param view: 
     46         :return: True,表示可以通过;False表示已超过限制,不允许访问
     47         """
     48         # 获取用户唯一标识(如:IP)
     49 
     50         # 允许一分钟访问10次
     51         num_request = 10
     52         time_request = 60
     53 
     54         now = self.ctime()
     55         ident = self.get_ident(request)
     56         self.ident = ident
     57         if ident not in RECORD:
     58             RECORD[ident] = [now, ]
     59             return True
     60         history = RECORD[ident]
     61         while history and history[-1] <= now - time_request:
     62             history.pop()
     63         if len(history) < num_request:
     64             history.insert(0, now)
     65             return True
     66 
     67     def wait(self):
     68         """
     69         多少秒后可以允许继续访问
     70         Optionally, return a recommended number of seconds to wait before
     71         the next request.
     72         """
     73         last_time = RECORD[self.ident][0]
     74         now = self.ctime()
     75         return int(60 + last_time - now)
     76 
     77 
     78 class TestView(APIView):
     79     throttle_classes = [TestThrottle, ]
     80 
     81     def get(self, request, *args, **kwargs):
     82         # self.dispatch
     83         print(request.user)
     84         print(request.auth)
     85         return Response('GET请求,响应内容')
     86 
     87     def post(self, request, *args, **kwargs):
     88         return Response('POST请求,响应内容')
     89 
     90     def put(self, request, *args, **kwargs):
     91         return Response('PUT请求,响应内容')
     92 
     93     def throttled(self, request, wait):
     94         """
     95         访问次数被限制时,定制错误信息
     96         """
     97 
     98         class Throttled(exceptions.Throttled):
     99             default_detail = '请求被限制.'
    100             extra_detail_singular = '请 {wait} 秒之后再重试.'
    101             extra_detail_plural = '请 {wait} 秒之后再重试.'
    102 
    103         raise Throttled(wait)
    views.py

    2、基于用户IP显示访问频率(利于Django缓存)

    1 REST_FRAMEWORK = {
    2     'DEFAULT_THROTTLE_RATES': {
    3         'test_scope': '10/m',
    4     },
    5 }
    settings.py
    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view()),
    6 ]
    urls.py
    views.py

    3、view中限制请求频率

    1 REST_FRAMEWORK = {
    2     'DEFAULT_THROTTLE_RATES': {
    3         'xxxxxx': '10/m',
    4     },
    5 }
    settings.py
    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view()),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 
     6 from rest_framework import exceptions
     7 from rest_framework.throttling import ScopedRateThrottle
     8 
     9 
    10 # 继承 ScopedRateThrottle
    11 class TestThrottle(ScopedRateThrottle):
    12 
    13     def get_cache_key(self, request, view):
    14         """
    15         Should return a unique cache-key which can be used for throttling.
    16         Must be overridden.
    17 
    18         May return `None` if the request should not be throttled.
    19         """
    20         if not request.user:
    21             ident = self.get_ident(request)
    22         else:
    23             ident = request.user
    24 
    25         return self.cache_format % {
    26             'scope': self.scope,
    27             'ident': ident
    28         }
    29 
    30 
    31 class TestView(APIView):
    32     throttle_classes = [TestThrottle, ]
    33 
    34     # 在settings中获取 xxxxxx 对应的频率限制值
    35     throttle_scope = "xxxxxx"
    36 
    37     def get(self, request, *args, **kwargs):
    38         # self.dispatch
    39         print(request.user)
    40         print(request.auth)
    41         return Response('GET请求,响应内容')
    42 
    43     def post(self, request, *args, **kwargs):
    44         return Response('POST请求,响应内容')
    45 
    46     def put(self, request, *args, **kwargs):
    47         return Response('PUT请求,响应内容')
    48 
    49     def throttled(self, request, wait):
    50         """
    51         访问次数被限制时,定制错误信息
    52         """
    53 
    54         class Throttled(exceptions.Throttled):
    55             default_detail = '请求被限制.'
    56             extra_detail_singular = '请 {wait} 秒之后再重试.'
    57             extra_detail_plural = '请 {wait} 秒之后再重试.'
    58 
    59         raise Throttled(wait)
    views.py

    4、匿名时用IP限制+登录时用Token限制

    1 REST_FRAMEWORK = {
    2     'UNAUTHENTICATED_USER': None,
    3     'UNAUTHENTICATED_TOKEN': None,
    4     'DEFAULT_THROTTLE_RATES': {
    5         'luffy_anon': '10/m',
    6         'luffy_user': '20/m',
    7     },
    8 }
    settings.py
    1 from django.conf.urls import url, include
    2 from web.views.s3_throttling import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view()),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 
     6 from rest_framework.throttling import SimpleRateThrottle
     7 
     8 
     9 class LuffyAnonRateThrottle(SimpleRateThrottle):
    10     """
    11     匿名用户,根据IP进行限制
    12     """
    13     scope = "luffy_anon"
    14 
    15     def get_cache_key(self, request, view):
    16         # 用户已登录,则跳过 匿名频率限制
    17         if request.user:
    18             return None
    19 
    20         return self.cache_format % {
    21             'scope': self.scope,
    22             'ident': self.get_ident(request)
    23         }
    24 
    25 
    26 class LuffyUserRateThrottle(SimpleRateThrottle):
    27     """
    28     登录用户,根据用户token限制
    29     """
    30     scope = "luffy_user"
    31 
    32     def get_ident(self, request):
    33         """
    34         认证成功时:request.user是用户对象;request.auth是token对象
    35         :param request: 
    36         :return: 
    37         """
    38         # return request.auth.token
    39         return "user_token"
    40 
    41     def get_cache_key(self, request, view):
    42         """
    43         获取缓存key
    44         :param request: 
    45         :param view: 
    46         :return: 
    47         """
    48         # 未登录用户,则跳过 Token限制
    49         if not request.user:
    50             return None
    51 
    52         return self.cache_format % {
    53             'scope': self.scope,
    54             'ident': self.get_ident(request)
    55         }
    56 
    57 
    58 class TestView(APIView):
    59     throttle_classes = [LuffyUserRateThrottle, LuffyAnonRateThrottle, ]
    60 
    61     def get(self, request, *args, **kwargs):
    62         # self.dispatch
    63         print(request.user)
    64         print(request.auth)
    65         return Response('GET请求,响应内容')
    66 
    67     def post(self, request, *args, **kwargs):
    68         return Response('POST请求,响应内容')
    69 
    70     def put(self, request, *args, **kwargs):
    71         return Response('PUT请求,响应内容')
    views.py

    5、全局使用

     1 REST_FRAMEWORK = {
     2     'DEFAULT_THROTTLE_CLASSES': [
     3         'api.utils.throttles.throttles.LuffyAnonRateThrottle',
     4         'api.utils.throttles.throttles.LuffyUserRateThrottle',
     5     ],
     6     'DEFAULT_THROTTLE_RATES': {
     7         'anon': '10/day',
     8         'user': '10/day',
     9         'luffy_anon': '10/m',
    10         'luffy_user': '20/m',
    11     },
    12 }
    settings.py

    4.4版本

    1、基于url的get传参方式

    如:/users?version=v1

    1 REST_FRAMEWORK = {
    2     'DEFAULT_VERSION': 'v1',            # 默认版本
    3     'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    4     'VERSION_PARAM': 'version'          # URL中获取值的key
    5 }
    settings
    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view(),name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.versioning import QueryParameterVersioning
     6 
     7 
     8 class TestView(APIView):
     9     versioning_class = QueryParameterVersioning
    10 
    11     def get(self, request, *args, **kwargs):
    12 
    13         # 获取版本
    14         print(request.version)
    15         # 获取版本管理的类
    16         print(request.versioning_scheme)
    17 
    18         # 反向生成URL
    19         reverse_url = request.versioning_scheme.reverse('test', request=request)
    20         print(reverse_url)
    21 
    22         return Response('GET请求,响应内容')
    23 
    24     def post(self, request, *args, **kwargs):
    25         return Response('POST请求,响应内容')
    26 
    27     def put(self, request, *args, **kwargs):
    28         return Response('PUT请求,响应内容')
    view.py

    2、基于url的正则方式

    如:/v1/users/

    1 REST_FRAMEWORK = {
    2     'DEFAULT_VERSION': 'v1',            # 默认版本
    3     'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    4     'VERSION_PARAM': 'version'          # URL中获取值的key
    5 }
    settings.py
    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^(?P<version>[v1|v2]+)/test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.versioning import URLPathVersioning
     6 
     7 
     8 class TestView(APIView):
     9     versioning_class = URLPathVersioning
    10 
    11     def get(self, request, *args, **kwargs):
    12         # 获取版本
    13         print(request.version)
    14         # 获取版本管理的类
    15         print(request.versioning_scheme)
    16 
    17         # 反向生成URL
    18         reverse_url = request.versioning_scheme.reverse('test', request=request)
    19         print(reverse_url)
    20 
    21         return Response('GET请求,响应内容')
    22 
    23     def post(self, request, *args, **kwargs):
    24         return Response('POST请求,响应内容')
    25 
    26     def put(self, request, *args, **kwargs):
    27         return Response('PUT请求,响应内容')
    views.py

    3、基于 accept 请求头方式

    如:Accept: application/json; version=1.0

    1 REST_FRAMEWORK = {
    2     'DEFAULT_VERSION': 'v1',            # 默认版本
    3     'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    4     'VERSION_PARAM': 'version'          # URL中获取值的key
    5 }
    settings.py
    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.versioning import AcceptHeaderVersioning
     6 
     7 
     8 class TestView(APIView):
     9     versioning_class = AcceptHeaderVersioning
    10 
    11     def get(self, request, *args, **kwargs):
    12         # 获取版本 HTTP_ACCEPT头
    13         print(request.version)
    14         # 获取版本管理的类
    15         print(request.versioning_scheme)
    16         # 反向生成URL
    17         reverse_url = request.versioning_scheme.reverse('test', request=request)
    18         print(reverse_url)
    19 
    20         return Response('GET请求,响应内容')
    21 
    22     def post(self, request, *args, **kwargs):
    23         return Response('POST请求,响应内容')
    24 
    25     def put(self, request, *args, **kwargs):
    26         return Response('PUT请求,响应内容')
    views.py

    4、基于主机名方法

    如:v1.example.com

    1 ALLOWED_HOSTS = ['*']
    2 REST_FRAMEWORK = {
    3     'DEFAULT_VERSION': 'v1',  # 默认版本
    4     'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
    5     'VERSION_PARAM': 'version'  # URL中获取值的key
    6 }
    settings.py
    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'^test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.versioning import HostNameVersioning
     6 
     7 
     8 class TestView(APIView):
     9     versioning_class = HostNameVersioning
    10 
    11     def get(self, request, *args, **kwargs):
    12         # 获取版本
    13         print(request.version)
    14         # 获取版本管理的类
    15         print(request.versioning_scheme)
    16         # 反向生成URL
    17         reverse_url = request.versioning_scheme.reverse('test', request=request)
    18         print(reverse_url)
    19 
    20         return Response('GET请求,响应内容')
    21 
    22     def post(self, request, *args, **kwargs):
    23         return Response('POST请求,响应内容')
    24 
    25     def put(self, request, *args, **kwargs):
    26         return Response('PUT请求,响应内容')
    views.py

    5、基于django路由系统的namespace

    如:example.com/v1/users/

    1 REST_FRAMEWORK = {
    2     'DEFAULT_VERSION': 'v1',  # 默认版本
    3     'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
    4     'VERSION_PARAM': 'version'  # URL中获取值的key
    5 }
    settings.py
     1 from django.conf.urls import url, include
     2 from web.views import TestView
     3 
     4 urlpatterns = [
     5     url(r'^v1/', ([
     6                       url(r'test/', TestView.as_view(), name='test'),
     7                   ], None, 'v1')),
     8     url(r'^v2/', ([
     9                       url(r'test/', TestView.as_view(), name='test'),
    10                   ], None, 'v2')),
    11 
    12 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.versioning import NamespaceVersioning
     6 
     7 
     8 class TestView(APIView):
     9     versioning_class = NamespaceVersioning
    10 
    11     def get(self, request, *args, **kwargs):
    12         # 获取版本
    13         print(request.version)
    14         # 获取版本管理的类
    15         print(request.versioning_scheme)
    16         # 反向生成URL
    17         reverse_url = request.versioning_scheme.reverse('test', request=request)
    18         print(reverse_url)
    19 
    20         return Response('GET请求,响应内容')
    21 
    22     def post(self, request, *args, **kwargs):
    23         return Response('POST请求,响应内容')
    24 
    25     def put(self, request, *args, **kwargs):
    26         return Response('PUT请求,响应内容')
    views.py

    6、全局使用

    1 REST_FRAMEWORK = {
    2     'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
    3     'DEFAULT_VERSION': 'v1',
    4     'ALLOWED_VERSIONS': ['v1', 'v2'],
    5     'VERSION_PARAM': 'version' 
    6 }
    settings.py

    4.5解释器(parser)

    根据请求头 content-type 选择对应的解析器就请求体内容进行处理。

    1、仅处理请求头content-type为application/json的请求体

    1 from django.conf.urls import url, include
    2 from web.views.s5_parser import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.request import Request
     6 from rest_framework.parsers import JSONParser
     7 
     8 
     9 class TestView(APIView):
    10     parser_classes = [JSONParser, ]
    11 
    12     def post(self, request, *args, **kwargs):
    13         print(request.content_type)
    14 
    15         # 获取请求的值,并使用对应的JSONParser进行处理
    16         print(request.data)
    17 
    18         # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
    19         print(request.POST)
    20         print(request.FILES)
    21 
    22         return Response('POST请求,响应内容')
    23 
    24     def put(self, request, *args, **kwargs):
    25         return Response('PUT请求,响应内容')
    views.py

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

    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.request import Request
     6 from rest_framework.parsers import FormParser
     7 
     8 
     9 class TestView(APIView):
    10     parser_classes = [FormParser, ]
    11 
    12     def post(self, request, *args, **kwargs):
    13         print(request.content_type)
    14 
    15         # 获取请求的值,并使用对应的JSONParser进行处理
    16         print(request.data)
    17 
    18         # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
    19         print(request.POST)
    20         print(request.FILES)
    21 
    22         return Response('POST请求,响应内容')
    23 
    24     def put(self, request, *args, **kwargs):
    25         return Response('PUT请求,响应内容')
    views.py

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

    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.request import Request
     6 from rest_framework.parsers import MultiPartParser
     7 
     8 
     9 class TestView(APIView):
    10     parser_classes = [MultiPartParser, ]
    11 
    12     def post(self, request, *args, **kwargs):
    13         print(request.content_type)
    14 
    15         # 获取请求的值,并使用对应的JSONParser进行处理
    16         print(request.data)
    17         # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
    18         print(request.POST)
    19         print(request.FILES)
    20         return Response('POST请求,响应内容')
    21 
    22     def put(self, request, *args, **kwargs):
    23         return Response('PUT请求,响应内容')
    views.py
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8 <form action="http://127.0.0.1:8000/test/" method="post" enctype="multipart/form-data">
     9     <input type="text" name="user" />
    10     <input type="file" name="img">
    11 
    12     <input type="submit" value="提交">
    13 
    14 </form>
    15 </body>
    16 </html>
    upload.py

    4、仅上传文件

    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.request import Request
     6 from rest_framework.parsers import FileUploadParser
     7 
     8 
     9 class TestView(APIView):
    10     parser_classes = [FileUploadParser, ]
    11 
    12     def post(self, request, filename, *args, **kwargs):
    13         print(filename)
    14         print(request.content_type)
    15 
    16         # 获取请求的值,并使用对应的JSONParser进行处理
    17         print(request.data)
    18         # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
    19         print(request.POST)
    20         print(request.FILES)
    21         return Response('POST请求,响应内容')
    22 
    23     def put(self, request, *args, **kwargs):
    24         return Response('PUT请求,响应内容')
    views.py
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8 <form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
     9     <input type="text" name="user" />
    10     <input type="file" name="img">
    11 
    12     <input type="submit" value="提交">
    13 
    14 </form>
    15 </body>
    16 </html>
    17 复制代码
    upload.py

    5、同时多个Parser

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

    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework.request import Request
     6 from rest_framework.parsers import JSONParser, FormParser, MultiPartParser
     7 
     8 
     9 class TestView(APIView):
    10     parser_classes = [JSONParser, FormParser, MultiPartParser, ]
    11 
    12     def post(self, request, *args, **kwargs):
    13         print(request.content_type)
    14 
    15         # 获取请求的值,并使用对应的JSONParser进行处理
    16         print(request.data)
    17         # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
    18         print(request.POST)
    19         print(request.FILES)
    20         return Response('POST请求,响应内容')
    21 
    22     def put(self, request, *args, **kwargs):
    23         return Response('PUT请求,响应内容')
    views.py

    6、全局使用

    1 REST_FRAMEWORK = {
    2     'DEFAULT_PARSER_CLASSES':[
    3         'rest_framework.parsers.JSONParser'
    4         'rest_framework.parsers.FormParser'
    5         'rest_framework.parsers.MultiPartParser'
    6     ]
    7 
    8 }
    settings.py
    1 from django.conf.urls import url, include
    2 from web.views import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 from rest_framework.views import APIView
     2 from rest_framework.response import Response
     3 
     4 
     5 class TestView(APIView):
     6     def post(self, request, *args, **kwargs):
     7         print(request.content_type)
     8 
     9         # 获取请求的值,并使用对应的JSONParser进行处理
    10         print(request.data)
    11         # application/x-www-form-urlencoded 或 multipart/form-data时,request.POST中才有值
    12         print(request.POST)
    13         print(request.FILES)
    14         return Response('POST请求,响应内容')
    15 
    16     def put(self, request, *args, **kwargs):
    17         return Response('PUT请求,响应内容')
    views.py

    注意:个别特殊的值可以通过Django的request对象 request._request 来进行获取

    4.6序列化

    序列化用于对用户请求数据进行验证和数据进行序列化。

    1、自定义字段

    1 from django.conf.urls import url, include
    2 from web.views.s6_serializers import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 from .. import models
     7 
     8 
     9 class PasswordValidator(object):
    10     def __init__(self, base):
    11         self.base = base
    12 
    13     def __call__(self, value):
    14         if value != self.base:
    15             message = 'This field must be %s.' % self.base
    16             raise serializers.ValidationError(message)
    17 
    18     def set_context(self, serializer_field):
    19         """
    20         This hook is called by the serializer instance,
    21         prior to the validation call being made.
    22         """
    23         # 执行验证之前调用,serializer_fields是当前字段对象
    24         pass
    25 
    26 
    27 class UserSerializer(serializers.Serializer):
    28     ut_title = serializers.CharField(source='ut.title')
    29     user = serializers.CharField(min_length=6)
    30     pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('666')])
    31 
    32 
    33 class TestView(APIView):
    34     def get(self, request, *args, **kwargs):
    35 
    36         # 序列化,将数据库查询字段序列化为字典
    37         data_list = models.UserInfo.objects.all()
    38         ser = UserSerializer(instance=data_list, many=True)
    39         #
    40         # obj = models.UserInfo.objects.all().first()
    41         # ser = UserSerializer(instance=obj, many=False)
    42         return Response(ser.data)
    43 
    44     def post(self, request, *args, **kwargs):
    45         # 验证,对请求发来的数据进行验证
    46         ser = UserSerializer(data=request.data)
    47         if ser.is_valid():
    48             print(ser.validated_data)
    49         else:
    50             print(ser.errors)
    51 
    52         return Response('POST请求,响应内容')
    views.py

    2、基于Model自动生成字段

    1 from django.conf.urls import url, include
    2 from web.views.s6_serializers import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 from .. import models
     7 
     8 
     9 class PasswordValidator(object):
    10     def __init__(self, base):
    11         self.base = str(base)
    12 
    13     def __call__(self, value):
    14         if value != self.base:
    15             message = 'This field must be %s.' % self.base
    16             raise serializers.ValidationError(message)
    17 
    18     def set_context(self, serializer_field):
    19         """
    20         This hook is called by the serializer instance,
    21         prior to the validation call being made.
    22         """
    23         # 执行验证之前调用,serializer_fields是当前字段对象
    24         pass
    25 
    26 class ModelUserSerializer(serializers.ModelSerializer):
    27 
    28     user = serializers.CharField(max_length=32)
    29 
    30     class Meta:
    31         model = models.UserInfo
    32         fields = "__all__"
    33         # fields = ['user', 'pwd', 'ut']
    34         depth = 2
    35         extra_kwargs = {'user': {'min_length': 6}, 'pwd': {'validators': [PasswordValidator(666), ]}}
    36         # read_only_fields = ['user']
    37 
    38 
    39 class TestView(APIView):
    40     def get(self, request, *args, **kwargs):
    41 
    42         # 序列化,将数据库查询字段序列化为字典
    43         data_list = models.UserInfo.objects.all()
    44         ser = ModelUserSerializer(instance=data_list, many=True)
    45         #
    46         # obj = models.UserInfo.objects.all().first()
    47         # ser = UserSerializer(instance=obj, many=False)
    48         return Response(ser.data)
    49 
    50     def post(self, request, *args, **kwargs):
    51         # 验证,对请求发来的数据进行验证
    52         print(request.data)
    53         ser = ModelUserSerializer(data=request.data)
    54         if ser.is_valid():
    55             print(ser.validated_data)
    56         else:
    57             print(ser.errors)
    58 
    59         return Response('POST请求,响应内容')
    views.py

    3、生成URL

    1 from django.conf.urls import url, include
    2 from web.views.s6_serializers import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6     url(r'detail/(?P<pk>d+)/', TestView.as_view(), name='detail'),
    7 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 from .. import models
     7 
     8 
     9 class PasswordValidator(object):
    10     def __init__(self, base):
    11         self.base = str(base)
    12 
    13     def __call__(self, value):
    14         if value != self.base:
    15             message = 'This field must be %s.' % self.base
    16             raise serializers.ValidationError(message)
    17 
    18     def set_context(self, serializer_field):
    19         """
    20         This hook is called by the serializer instance,
    21         prior to the validation call being made.
    22         """
    23         # 执行验证之前调用,serializer_fields是当前字段对象
    24         pass
    25 
    26 
    27 class ModelUserSerializer(serializers.ModelSerializer):
    28     ut = serializers.HyperlinkedIdentityField(view_name='detail')
    29     class Meta:
    30         model = models.UserInfo
    31         fields = "__all__"
    32 
    33         extra_kwargs = {
    34             'user': {'min_length': 6},
    35             'pwd': {'validators': [PasswordValidator(666),]},
    36         }
    37 
    38 
    39 
    40 class TestView(APIView):
    41     def get(self, request, *args, **kwargs):
    42 
    43         # 序列化,将数据库查询字段序列化为字典
    44         data_list = models.UserInfo.objects.all()
    45         ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request})
    46         #
    47         # obj = models.UserInfo.objects.all().first()
    48         # ser = UserSerializer(instance=obj, many=False)
    49         return Response(ser.data)
    50 
    51     def post(self, request, *args, **kwargs):
    52         # 验证,对请求发来的数据进行验证
    53         print(request.data)
    54         ser = ModelUserSerializer(data=request.data)
    55         if ser.is_valid():
    56             print(ser.validated_data)
    57         else:
    58             print(ser.errors)
    59 
    60         return Response('POST请求,响应内容')
    views.py

    4、自动生成URL

    1 from django.conf.urls import url, include
    2 from web.views.s6_serializers import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view(), name='test'),
    6     url(r'detail/(?P<pk>d+)/', TestView.as_view(), name='xxxx'),
    7 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 from .. import models
     7 
     8 
     9 class PasswordValidator(object):
    10     def __init__(self, base):
    11         self.base = str(base)
    12 
    13     def __call__(self, value):
    14         if value != self.base:
    15             message = 'This field must be %s.' % self.base
    16             raise serializers.ValidationError(message)
    17 
    18     def set_context(self, serializer_field):
    19         """
    20         This hook is called by the serializer instance,
    21         prior to the validation call being made.
    22         """
    23         # 执行验证之前调用,serializer_fields是当前字段对象
    24         pass
    25 
    26 
    27 class ModelUserSerializer(serializers.HyperlinkedModelSerializer):
    28     ll = serializers.HyperlinkedIdentityField(view_name='xxxx')
    29     tt = serializers.CharField(required=False)
    30 
    31     class Meta:
    32         model = models.UserInfo
    33         fields = "__all__"
    34         list_serializer_class = serializers.ListSerializer
    35 
    36         extra_kwargs = {
    37             'user': {'min_length': 6},
    38             'pwd': {'validators': [PasswordValidator(666), ]},
    39             'url': {'view_name': 'xxxx'},
    40             'ut': {'view_name': 'xxxx'},
    41         }
    42 
    43 
    44 class TestView(APIView):
    45     def get(self, request, *args, **kwargs):
    46         # # 序列化,将数据库查询字段序列化为字典
    47         data_list = models.UserInfo.objects.all()
    48         ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request})
    49         # # 如果Many=True
    50         # # 或
    51         # # obj = models.UserInfo.objects.all().first()
    52         # # ser = UserSerializer(instance=obj, many=False)
    53         return Response(ser.data)
    54 
    55     def post(self, request, *args, **kwargs):
    56         # 验证,对请求发来的数据进行验证
    57         print(request.data)
    58         ser = ModelUserSerializer(data=request.data)
    59         if ser.is_valid():
    60             print(ser.validated_data)
    61         else:
    62             print(ser.errors)
    63 
    64         return Response('POST请求,响应内容')
    views.py

    4.7分页

    1、根据页码进行分页

    1 from django.conf.urls import url, include
    2 from rest_framework import routers
    3 from web.views import s9_pagination
    4 
    5 urlpatterns = [
    6     url(r'^test/', s9_pagination.UserViewSet.as_view()),
    7 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework import serializers
     5 from .. import models
     6 
     7 from rest_framework.pagination import PageNumberPagination
     8 
     9 
    10 class StandardResultsSetPagination(PageNumberPagination):
    11     # 默认每页显示的数据条数
    12     page_size = 1
    13     # 获取URL参数中设置的每页显示数据条数
    14     page_size_query_param = 'page_size'
    15 
    16     # 获取URL参数中传入的页码key
    17     page_query_param = 'page'
    18 
    19     # 最大支持的每页显示的数据条数
    20     max_page_size = 1
    21 
    22 
    23 class UserSerializer(serializers.ModelSerializer):
    24     class Meta:
    25         model = models.UserInfo
    26         fields = "__all__"
    27 
    28 
    29 class UserViewSet(APIView):
    30     def get(self, request, *args, **kwargs):
    31         user_list = models.UserInfo.objects.all().order_by('-id')
    32 
    33         # 实例化分页对象,获取数据库中的分页数据
    34         paginator = StandardResultsSetPagination()
    35         page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)
    36 
    37         # 序列化对象
    38         serializer = UserSerializer(page_user_list, many=True)
    39 
    40         # 生成分页和数据
    41         response = paginator.get_paginated_response(serializer.data)
    42         return response
    views.py

    2、位置和个数进行分页

    1 from django.conf.urls import url, include
    2 from web.views import s9_pagination
    3 
    4 urlpatterns = [
    5     url(r'^test/', s9_pagination.UserViewSet.as_view()),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework import serializers
     5 from .. import models
     6 
     7 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
     8 
     9 
    10 class StandardResultsSetPagination(LimitOffsetPagination):
    11     # 默认每页显示的数据条数
    12     default_limit = 10
    13     # URL中传入的显示数据条数的参数
    14     limit_query_param = 'limit'
    15     # URL中传入的数据位置的参数
    16     offset_query_param = 'offset'
    17     # 最大每页显得条数
    18     max_limit = None
    19 
    20 class UserSerializer(serializers.ModelSerializer):
    21     class Meta:
    22         model = models.UserInfo
    23         fields = "__all__"
    24 
    25 
    26 class UserViewSet(APIView):
    27     def get(self, request, *args, **kwargs):
    28         user_list = models.UserInfo.objects.all().order_by('-id')
    29 
    30         # 实例化分页对象,获取数据库中的分页数据
    31         paginator = StandardResultsSetPagination()
    32         page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)
    33 
    34         # 序列化对象
    35         serializer = UserSerializer(page_user_list, many=True)
    36 
    37         # 生成分页和数据
    38         response = paginator.get_paginated_response(serializer.data)
    39         return response
    views.py

    3、游标分页

    1 from django.conf.urls import url, include
    2 from web.views import s9_pagination
    3 
    4 urlpatterns = [
    5     url(r'^test/', s9_pagination.UserViewSet.as_view()),
    6 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework import serializers
     5 from .. import models
     6 
     7 from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
     8 
     9 
    10 class StandardResultsSetPagination(CursorPagination):
    11     # URL传入的游标参数
    12     cursor_query_param = 'cursor'
    13     # 默认每页显示的数据条数
    14     page_size = 2
    15     # URL传入的每页显示条数的参数
    16     page_size_query_param = 'page_size'
    17     # 每页显示数据最大条数
    18     max_page_size = 1000
    19 
    20     # 根据ID从大到小排列
    21     ordering = "id"
    22 
    23 
    24 
    25 class UserSerializer(serializers.ModelSerializer):
    26     class Meta:
    27         model = models.UserInfo
    28         fields = "__all__"
    29 
    30 
    31 class UserViewSet(APIView):
    32     def get(self, request, *args, **kwargs):
    33         user_list = models.UserInfo.objects.all().order_by('-id')
    34 
    35         # 实例化分页对象,获取数据库中的分页数据
    36         paginator = StandardResultsSetPagination()
    37         page_user_list = paginator.paginate_queryset(user_list, self.request, view=self)
    38 
    39         # 序列化对象
    40         serializer = UserSerializer(page_user_list, many=True)
    41 
    42         # 生成分页和数据
    43         response = paginator.get_paginated_response(serializer.data)
    44         return response
    views.py

    4.8路由系统

    1、自定义路由

    1 from django.conf.urls import url, include
    2 from web.views import s11_render
    3 
    4 urlpatterns = [
    5     url(r'^test/$', s11_render.TestView.as_view()),
    6     url(r'^test.(?P<format>[a-z0-9]+)$', s11_render.TestView.as_view()),
    7     url(r'^test/(?P<pk>[^/.]+)/$', s11_render.TestView.as_view()),
    8     url(r'^test/(?P<pk>[^/.]+).(?P<format>[a-z0-9]+)$', s11_render.TestView.as_view())
    9 ]
    urls.py
     1 from rest_framework.views import APIView
     2 from rest_framework.response import Response
     3 from .. import models
     4 
     5 
     6 class TestView(APIView):
     7     def get(self, request, *args, **kwargs):
     8         print(kwargs)
     9         print(self.renderer_classes)
    10         return Response('...')
    views.py

    2、半自动路由

    1 from django.conf.urls import url, include
    2 from web.views import s10_generic
    3 
    4 urlpatterns = [
    5     url(r'^test/$', s10_generic.UserViewSet.as_view({'get': 'list', 'post': 'create'})),
    6     url(r'^test/(?P<pk>d+)/$', s10_generic.UserViewSet.as_view(
    7         {'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
    8 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.viewsets import ModelViewSet
     4 from rest_framework import serializers
     5 from .. import models
     6 
     7 
     8 class UserSerializer(serializers.ModelSerializer):
     9     class Meta:
    10         model = models.UserInfo
    11         fields = "__all__"
    12 
    13 
    14 class UserViewSet(ModelViewSet):
    15     queryset = models.UserInfo.objects.all()
    16     serializer_class = UserSerializer
    views.py

    3、全自动路由

     1 from django.conf.urls import url, include
     2 from rest_framework import routers
     3 from web.views import s10_generic
     4 
     5 
     6 router = routers.DefaultRouter()
     7 router.register(r'users', s10_generic.UserViewSet)
     8 
     9 urlpatterns = [
    10     url(r'^', include(router.urls)),
    11 ]
    urls.py
     1 from rest_framework.viewsets import ModelViewSet
     2 from rest_framework import serializers
     3 from .. import models
     4 
     5 
     6 class UserSerializer(serializers.ModelSerializer):
     7     class Meta:
     8         model = models.UserInfo
     9         fields = "__all__"
    10 
    11 
    12 class UserViewSet(ModelViewSet):
    13     queryset = models.UserInfo.objects.all()
    14     serializer_class = UserSerializer
    views.py

    4.9视图

    1、GenericViewSet

    1 from django.conf.urls import url, include
    2 from web.views.s7_viewset import TestView
    3 
    4 urlpatterns = [
    5     url(r'test/', TestView.as_view({'get':'list'}), name='test'),
    6     url(r'detail/(?P<pk>d+)/', TestView.as_view({'get':'list'}), name='xxxx'),
    7 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework import viewsets
     4 from rest_framework.response import Response
     5 
     6 
     7 class TestView(viewsets.GenericViewSet):
     8     def list(self, request, *args, **kwargs):
     9         return Response('...')
    10 
    11     def add(self, request, *args, **kwargs):
    12         pass
    13 
    14     def delete(self, request, *args, **kwargs):
    15         pass
    16 
    17     def edit(self, request, *args, **kwargs):
    18         pass
    views.py

    2、ModelViewSet(自定义URL)

    1 from django.conf.urls import url, include
    2 from web.views import s10_generic
    3 
    4 urlpatterns = [
    5     url(r'^test/$', s10_generic.UserViewSet.as_view({'get': 'list', 'post': 'create'})),
    6     url(r'^test/(?P<pk>d+)/$', s10_generic.UserViewSet.as_view(
    7         {'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
    8 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.viewsets import ModelViewSet
     4 from rest_framework import serializers
     5 from .. import models
     6 
     7 
     8 class UserSerializer(serializers.ModelSerializer):
     9     class Meta:
    10         model = models.UserInfo
    11         fields = "__all__"
    12 
    13 
    14 class UserViewSet(ModelViewSet):
    15     queryset = models.UserInfo.objects.all()
    16     serializer_class = UserSerializer
    views.py

    3、ModelViewSet(rest framework路由)

     1 from django.conf.urls import url, include
     2 from rest_framework import routers
     3 from app01 import views
     4 
     5 router = routers.DefaultRouter()
     6 router.register(r'users', views.UserViewSet)
     7 router.register(r'groups', views.GroupViewSet)
     8 
     9 # Wire up our API using automatic URL routing.
    10 # Additionally, we include login URLs for the browsable API.
    11 urlpatterns = [
    12     url(r'^', include(router.urls)),
    13 ]
    urls.py
     1 from rest_framework import viewsets
     2 from rest_framework import serializers
     3 
     4 
     5 class UserSerializer(serializers.HyperlinkedModelSerializer):
     6     class Meta:
     7         model = models.User
     8         fields = ('url', 'username', 'email', 'groups')
     9 
    10 
    11 class GroupSerializer(serializers.HyperlinkedModelSerializer):
    12     class Meta:
    13         model = models.Group
    14         fields = ('url', 'name')
    15         
    16 class UserViewSet(viewsets.ModelViewSet):
    17     """
    18     API endpoint that allows users to be viewed or edited.
    19     """
    20     queryset = User.objects.all().order_by('-date_joined')
    21     serializer_class = UserSerializer
    22 
    23 
    24 class GroupViewSet(viewsets.ModelViewSet):
    25     """
    26     API endpoint that allows groups to be viewed or edited.
    27     """
    28     queryset = Group.objects.all()
    29     serializer_class = GroupSerializer
    views.py

    4.10渲染器

    根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件。
    用户请求URL:

    • http://127.0.0.1:8000/test/?format=json
    • http://127.0.0.1:8000/test.json

    用户请求头:

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

    1、json

    访问URL:

      • http://127.0.0.1:8000/test/?format=json
      • http://127.0.0.1:8000/test.json
      • http://127.0.0.1:8000/test/ 
    1 from django.conf.urls import url, include
    2 from web.views import s11_render
    3 
    4 urlpatterns = [
    5     url(r'^test/$', s11_render.TestView.as_view()),
    6     url(r'^test.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()),
    7 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 
     7 from rest_framework.renderers import JSONRenderer
     8 
     9 from .. import models
    10 
    11 
    12 class TestSerializer(serializers.ModelSerializer):
    13     class Meta:
    14         model = models.UserInfo
    15         fields = "__all__"
    16 
    17 
    18 class TestView(APIView):
    19     renderer_classes = [JSONRenderer, ]
    20 
    21     def get(self, request, *args, **kwargs):
    22         user_list = models.UserInfo.objects.all()
    23         ser = TestSerializer(instance=user_list, many=True)
    24         return Response(ser.data)
    views.py

    2、 表格

    访问URL:

    • http://127.0.0.1:8000/test/?format=admin
    • http://127.0.0.1:8000/test.admin
    • http://127.0.0.1:8000/test/ 
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 
     7 from rest_framework.renderers import AdminRenderer
     8 
     9 from .. import models
    10 
    11 
    12 class TestSerializer(serializers.ModelSerializer):
    13     class Meta:
    14         model = models.UserInfo
    15         fields = "__all__"
    16 
    17 
    18 class TestView(APIView):
    19     renderer_classes = [AdminRenderer, ]
    20 
    21     def get(self, request, *args, **kwargs):
    22         user_list = models.UserInfo.objects.all()
    23         ser = TestSerializer(instance=user_list, many=True)
    24         return Response(ser.data)
    views.py

    3、 Form表单

    访问URL:

    • http://127.0.0.1:8000/test/?format=form
    • http://127.0.0.1:8000/test.form
    • http://127.0.0.1:8000/test/ 
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 
     7 from rest_framework.renderers import JSONRenderer
     8 from rest_framework.renderers import AdminRenderer
     9 from rest_framework.renderers import HTMLFormRenderer
    10 
    11 from .. import models
    12 
    13 
    14 class TestSerializer(serializers.ModelSerializer):
    15     class Meta:
    16         model = models.UserInfo
    17         fields = "__all__"
    18 
    19 
    20 class TestView(APIView):
    21     renderer_classes = [HTMLFormRenderer, ]
    22 
    23     def get(self, request, *args, **kwargs):
    24         user_list = models.UserInfo.objects.all().first()
    25         ser = TestSerializer(instance=user_list, many=False)
    26         return Response(ser.data)
    views.py

    4、自定义显示模板

    访问URL:

    • http://127.0.0.1:8000/test/?format=html
    • http://127.0.0.1:8000/test.html
    • http://127.0.0.1:8000/test/ 
    1 from django.conf.urls import url, include
    2 from web.views import s11_render
    3 
    4 urlpatterns = [
    5     url(r'^test/$', s11_render.TestView.as_view()),
    6     url(r'^test.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()),
    7 ]
    urls.py
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 from rest_framework.renderers import TemplateHTMLRenderer
     7 
     8 from .. import models
     9 
    10 
    11 class TestSerializer(serializers.ModelSerializer):
    12     class Meta:
    13         model = models.UserInfo
    14         fields = "__all__"
    15 
    16 
    17 class TestView(APIView):
    18     renderer_classes = [TemplateHTMLRenderer, ]
    19 
    20     def get(self, request, *args, **kwargs):
    21         user_list = models.UserInfo.objects.all().first()
    22         ser = TestSerializer(instance=user_list, many=False)
    23         return Response(ser.data, template_name='user_detail.html')
    views.py
     1 <!DOCTYPE html>
     2 <html lang="en">
     3 <head>
     4     <meta charset="UTF-8">
     5     <title>Title</title>
     6 </head>
     7 <body>
     8     {{ user }}
     9     {{ pwd }}
    10     {{ ut }}
    11 </body>
    12 </html>
    userdetail.html

    5、 浏览器格式API+JSON

    访问URL:

    • http://127.0.0.1:8000/test/?format=api
    • http://127.0.0.1:8000/test.api
    • http://127.0.0.1:8000/test/ 
     1 #!/usr/bin/env python
     2 # -*- coding:utf-8 -*-
     3 from rest_framework.views import APIView
     4 from rest_framework.response import Response
     5 from rest_framework import serializers
     6 
     7 from rest_framework.renderers import JSONRenderer
     8 from rest_framework.renderers import BrowsableAPIRenderer
     9 
    10 from .. import models
    11 
    12 
    13 class TestSerializer(serializers.ModelSerializer):
    14     class Meta:
    15         model = models.UserInfo
    16         fields = "__all__"
    17 
    18 
    19 class CustomBrowsableAPIRenderer(BrowsableAPIRenderer):
    20     def get_default_renderer(self, view):
    21         return JSONRenderer()
    22 
    23 
    24 class TestView(APIView):
    25     renderer_classes = [CustomBrowsableAPIRenderer, ]
    26 
    27     def get(self, request, *args, **kwargs):
    28         user_list = models.UserInfo.objects.all().first()
    29         ser = TestSerializer(instance=user_list, many=False)
    30         return Response(ser.data, template_name='user_detail.html')
    View Code

    注意:如果同时多个存在时,自动根据URL后缀来选择渲染器。

  • 相关阅读:
    Winform打包Exe Inno Setup
    electron build慢
    electron解压app.asar文件
    input readonly 禁止获得焦点 和选择
    JS export
    数据库插件 red-gate SQLToolbelt
    DataGridView修改值后,最后一个修改项页面不会刷新
    DbDataReaderExtensions DbDataRender转换为实体
    反射获得实体
    LINQ Expression AndAlso,OrElse和And,Or的区别
  • 原文地址:https://www.cnblogs.com/wangshuyang/p/9101299.html
Copyright © 2011-2022 走看看