原文链接:https://www.sxzhongrui.com/maple-shaw/p/7865767.html

1。什么是RESTful

  • REST 与技术无关。它代表了一种软件架构风格。 REST 是表述性状态传输的缩写。中文翻译是“代表性状态转移”
  • REST从资源的角度看待整个网络。它通过URL来标识分布在网络中某个节点的资源。客户端应用程序通过 URL 获取资源的表示。获取这些表示会导致这些应用程序更改状态
  • 所有的数据,无论是通过网络获取的,还是操作(增、删、改、查)的,都是资源。将所有数据视为资源,是 REST 区别于其他架构风格最本质的属性
  • 针对REST面向资源的架构风格,有人提出了一个新的结构概念,即:面向资源的架构(ROA:Resource Oriented Architecture)
返回顶部

2. RESTful API 设计

  • API与用户之间的通信协议始终使用HTTPs协议。
  • 域名
    • https://www.sxzhongrui.com/api/                           API非常简单
  • 版本
    • URL,例如:https://www.sxzhongrui.com/v1/
  • 路径,网络上的一切都被视为资源,并以名词的形式表达(可以是复数)
    • https://www.sxzhongrui.com/v1/zoos
    • https://www.sxzhongrui.com/v1/animals
    • https://www.sxzhongrui.com/v1/employees
  • 方法
    • GET:从服务器检索资源(一项或多项)
    • POST:在服务器上创建新资源
    • PUT :更新服务器上的资源(客户端提供完整更改的资源)
    • PATCH:更新服务器上的资源(客户端提供更改的属性)
    • DELETE:从服务器删除资源
  • 过滤,以url中上传参数的形式传递搜索条件
    • https://www.sxzhongrui.com/v1/zoos?limit=10:指定返回记录数​​
    • https://www.sxzhongrui.com/v1/zoos?offset=10:指定返回记录的起始位置
    • https://www.sxzhongrui.com/v1/zoos?page=2&per_page=100:指定第几页以及每页记录数​​
    • https://www.sxzhongrui.com/v1/zoos?sortby=name&order=asc:指定返回结果按照哪个属性排序,以及排序顺序
    • https://www.sxzhongrui.com/v1/zoos?animal_type_id=1:指定过滤条件
  • 状态代码
    200 OK - [GET]:服务器成功返回用户请求的数据。此操作是幂等的。
    201 CREATED - [POST/PUT/PATCH]:​​用户成功创建或修改数据。
    202 Accepted - [*]:表示一个请求已进入后台队列(异步任务)
    204 NO CONTENT - [DELETE]:用户成功删除数据。
    400 INVALID REQUEST - [POST/PUT/PATCH]:​​用户发出的请求存在错误。服务器不创建或修改数据。此操作是幂等的。
    401 Unauthorized - [*]:表示用户没有权限(token、用户名、密码错误)。
    403 Forbidden - [*] 表示用户已获得授权(与 401 错误相反),但访问被禁止。
    404 NOT FOUND - [*]:用户发出的请求是针对不存在的记录,服务器没有执行该操作。该操作是幂等的。
    406 Not Acceptable - [GET]:用户请求的格式不可用(例如用户请求JSON格式,但只有XML格式)。
    410 Gone -[GET]:用户请求的资源已被永久删除,不会再次获取。
    422 不可处理的实体 - [POST/PUT/PATCH] 创建对象时发生验证错误。
    500 INTERNAL SERVER ERROR - [*]:发生服务器错误,用户将无法确定请求是否成功。
    在此处查看更多信息:http://www.sxzhongrui.com/Protocols/rfc2616/rfc2616-sec10.html
  • 错误处理,当状态码为4xx时,应返回错误信息,以error为key。
    1
    2
    3
    {
    错误:“API 密钥无效”
    }
  • 返回结果。对于不同的操作,服务器返回给用户的结果应符合以下规范。
    1
    2
    3
    4
    5
    6
    GET /集合:返回资源对象的列表(数组)
    GET /集合/资源:返回单个资源对象
    POST /集合:返回新生成的资源对象
    PUT /集合/资源:返回完整的资源对象
    PATCH /集合/资源:返回完整的资源对象
    删除/集合/资源:返回空文档
  • Hypermedia API,RESTful API最好是Hypermedia,即在返回结果中提供其他API方法的链接,这样用户不用查看文档就知道下一步该做什么。
    1
    2
    3
    4
    5
    6
    {“链接”:{
    “rel”“集合 https://www.sxzhongrui.com/zoos”
    “href”“https://www.sxzhongrui.com/zoos”
    “标题”: “动物园列表”,
    “类型”“application/vnd.yourformat+json”
    }}

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

返回顶部

3.基于Django

路由系统:

1
2
3
urlpatterns =[
url(r'^用户',www.sxzhongrui.com_view()),
]

CBV 视图:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
来自 django.views 导入查看
来自django.http导入JsonResponse
班级用户(查看):
    def 获取(自我,请求,*args,**kwargs):
        结果= {
            '状态'正确
            '数据''响应数据'
        }
        返回 JsonResponse(结果,状态=200
 
    def 帖子(自我,请求,*args,**kwargs):
        结果= {
            '状态'True,
            '数据''响应数据'
        }
        返回 JsonResponse(结果,状态=200
回到顶部

四。基于Django Rest Framework框架实现

1。基本流程

www.sxzhongrui.com

1
2
3
4
5
6
来自 django.conf.urls 导入 url,包括
来自 web.views.s1_api 导入 TestView
 
urlpatterns= [
    url(r'^test/', www.sxzhongrui.com_view()),
]

www.sxzhongrui.com

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
来自 rest_framework.views 导入 APIView
来自 rest_framework.response导入 响应
 
 
 测试视图(APIView):
    def 调度(自我,请求,*args,**kwargs):
        """
        请求到来之后,都要执行调度方法,调度方法根据请求方式不同触发get/post/put等方法
         
注:APIView中的dispatch方法有很多很多功能
    """
返回 超级().dispatch(请求, *args, **kwargs)
def get(self,请求,*arg s,**kwargs):
返回 响应('GET请求,响应内容'
def 帖子(自我,请求,*arg s,**kwargs):
返回 响应('POST请求,响应内容'
def put(self,请求,*arg s,**kwargs):
返回 响应('PUT请求,响应内容'

以上就是restframework框架的基本流程。重要的函数是在APIView的dispatch中触发的。

2。身份验证和授权

a。用户url传入的token认证

from django.conf.urls import url, include
从 web.viewsimport TestView
url 模式 = [
url(r'^test/', www.sxzhongrui.com_view()),
】
从rest_framework.views导入APIView
从rest_framework.response导入响应
从rest_framework.authentication导入BaseAuthentication
从rest_framework.request导入请求
从rest_framework导入异常
令牌列表 = [
'sfsfss123kuf3j123',
'asijnfowerkkf9812',
]
类 TestAuthentication(BaseAuthentication):
def 验证(自我,请求):
”“”
用户认证,如果认证成功,返回一个元组:(user, user Token)
:参数请求:
:返回:
None 表示跳过验证;
如果跳过所有身份验证,则使用配置文件设置默认用户和令​​牌
self._authenticator = 无如果 api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER()
别的:
self.用户=无
如果 api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN()
别的:
self.auth = 无
(user,token)表示验证通过,设置用户名和Token;
身份验证失败异常
”“”
val = request.query_params.get('token')
如果 val 不在 token_list 中:
引发异常。AuthenticationFailed("用户身份验证失败")
return ('登录用户', '用户令牌')
defauthenticate_header(自身,请求):
”“”
返回一个字符串,用作“WWW-Authenticate”的值
“401 Unauthenticated”响应中的标头,如果
身份验证方案应返回“403 Permission Denied”响应。
”“”
# 验证失败时,返回响应头WWW-Authenticate对应的值
经过
类测试视图(APIView):
身份验证类 = [测试身份验证,]
权限类 = []
def get(自身, 请求, *args, **kwargs):
打印(请求.用户)
打印(请求.auth)
return Response('GET请求,响应内容')
def post(self, request, *args, **kwargs):return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

b。请求头认证

from django.conf.urls import url, include
从 web.viewsimport TestView
url 模式 = [
url(r'^test/', www.sxzhongrui.com_view()),
】
#!/usr/bin/env python
# -*- 编码:utf-8 -*-
从rest_framework.views导入APIView
从rest_framework.response导入响应
从rest_framework.authentication导入BaseAuthentication
从rest_framework.request导入请求
从rest_framework导入异常
令牌列表 = ['sfsfss123kuf3j123',
'asijnfowerkkf9812',
]
类 TestAuthentication(BaseAuthentication):
def 验证(自我,请求):
”“”
用户认证,如果认证成功,返回一个元组:(user, user Token)
:参数请求:
:返回:
None 表示跳过验证;
如果跳过所有身份验证,则使用配置文件设置默认用户和令​​牌
self._authenticator = 无
如果 api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER()
别的:
self.用户=无
如果 api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN()
别的:
self.auth = 无
(user,token)表示验证通过,设置用户名和Token;
身份验证失败异常
”“”
导入base64
auth = request.META.get('HTTP_AUTHORIZATION', b'')
如果授权:
auth = auth.encode('utf-8')
auth = auth.split()
如果不是 auth 或 auth[0].lower() != b'basic':
引发异常。AuthenticationFailed('身份验证失败')
如果 len(auth) != 2:
引发异常。AuthenticationFailed('身份验证失败')
用户名、部分、密码 = base64.b64decode(auth[1]).decode('utf-8').partition(':')
如果用户名 == 'alex' 且密码 == '123':return ('登录用户', '用户令牌')
别的:
引发异常。AuthenticationFailed('用户名或密码错误')
defauthenticate_header(自身,请求):
”“”
返回一个字符串,用作“WWW-Authenticate”的值
“401 Unauthenticated”响应中的标头,如果
身份验证方案应返回“403 Permission Denied”响应。
”“”
return '基本领域=api'
类测试视图(APIView):
身份验证类 = [测试身份验证,]
权限类 = []
def get(自身, 请求, *args, **kwargs):
打印(请求.用户)
打印(请求.auth)
return Response('GET请求,响应内容')
def post(self, request, *args, **kwargs):
return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

c. 多种认证规则

from django.conf.urls import url, include
从 web.views.s2_auth 导入 TestView
url 模式 = [
url(r'^test/', www.sxzhongrui.com_view()),
】
#!/usr/bin/env python
# -*- 编码:utf-8 -*-
从rest_framework.views导入APIView
从rest_framework.response导入响应
从rest_framework.authentication导入BaseAuthentication
从rest_framework.request导入请求
从rest_framework导入异常
令牌列表 = [
'sfsfss123kuf3j123',
'asijnfowerkkf9812',
]
类 Test1Authentication(BaseAuthentication):
def 验证(自我,请求):
”“”
用户认证,如果认证成功,返回一个元组:(user, user Token)
:参数请求:
:返回:
None 表示跳过验证;
如果跳过所有身份验证,则使用配置文件设置默认用户和令​​牌
self._authenticator = 无
如果 api_settings.UNAUTHENTICATED_USER:self.user = api_settings.UNAUTHENTICATED_USER() #默认值为:匿名用户
别的:
self.用户=无
如果 api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:无
别的:
self.auth = 无
(user,token)表示验证通过,设置用户名和Token;
身份验证失败异常
”“”
导入base64
auth = request.META.get('HTTP_AUTHORIZATION', b'')
如果授权:
auth = auth.encode('utf-8')
别的:
返回无
打印(验证,'xxxx')
auth = auth.split()
如果不是 auth 或 auth[0].lower() != b'basic':
引发异常。AuthenticationFailed('身份验证失败')
如果 len(auth) != 2:
引发异常。AuthenticationFailed('身份验证失败')
用户名、部分、密码 = base64.b64decode(auth[1]).decode('utf-8').partition(':')
如果用户名 == 'alex' 且密码 == '123':
return ('登录用户', '用户令牌')
别的:
引发异常。AuthenticationFailed('用户名或密码错误')
defauthenticate_header(自身,请求):
”“”
返回一个字符串,用作“WWW-Authenticate”的值
“401 Unauthenticated”响应中的标头,如果身份验证方案应返回“403 Permission Denied”响应。
”“”
# return '基本领域=api'
经过
类 Test2Authentication(BaseAuthentication):
def 验证(自我,请求):
”“”
用户认证,如果认证成功,返回一个元组:(user, user Token)
:参数请求:
:返回:
None 表示跳过验证;
如果跳过所有身份验证,则使用配置文件设置默认用户和令​​牌
self._authenticator = 无
如果 api_settings.UNAUTHENTICATED_USER:
self.user = api_settings.UNAUTHENTICATED_USER() #默认值为:匿名用户
别的:
self.用户=无
如果 api_settings.UNAUTHENTICATED_TOKEN:
self.auth = api_settings.UNAUTHENTICATED_TOKEN()# 默认值为:无
别的:
self.auth = 无
(user,token)表示验证通过,设置用户名和Token;
身份验证失败异常
”“”
val = request.query_params.get('token')
如果 val 不在 token_list 中:
引发异常。AuthenticationFailed("用户身份验证失败")
return ('登录用户', '用户令牌')
defauthenticate_header(自身,请求):
”“”
返回一个字符串,用作“WWW-Authenticate”的值
“401 Unauthenticated”响应中的标头,如果身份验证方案应返回“403 Permission Denied”响应。
”“”
经过
类测试视图(APIView):
身份验证类 = [测试 1 身份验证、测试 2 身份验证]
权限类 = []
def get(自身, 请求, *args, **kwargs):
打印(请求.用户)
打印(请求.auth)
return Response('GET请求,响应内容')
def post(self, request, *args, **kwargs):
return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

d.身份验证和权限

from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view()),
]
#!/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. 全局使用

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

REST_FRAMEWORK = {
'UNAUTHENTICATED_USER': None,
'UNAUTHENTICATED_TOKEN': None,
"DEFAULT_AUTHENTICATION_CLASSES": [
"web.utils.TestAuthentication",
],
"DEFAULT_PERMISSION_CLASSES": [
"web.utils.TestPermission",
],
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view()),
]
#!/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请求,响应内容')

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

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

from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view()),
]
#!/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缓存)

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'test_scope': '10/m',
},
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view()),
]
#!/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中限制请求频率

REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'xxxxxx': '10/m',
},
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view()),
]
#!/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限制

REST_FRAMEWORK = {
'UNAUTHENTICATED_USER': None,
'UNAUTHENTICATED_TOKEN': None,
'DEFAULT_THROTTLE_RATES': {
'luffy_anon': '10/m',
'luffy_user': '20/m',
},
}
from django.conf.urls import url, include
from web.views.s3_throttling import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view()),
]
#!/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. 全局使用

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',
},
}

4. 版本

a. 基于url的get传参方式

如:/users?version=v1

REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1',            # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
'VERSION_PARAM': 'version'          # URL中获取值的key
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view(),name='test'),
]
#!/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/

REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1',            # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
'VERSION_PARAM': 'version'          # URL中获取值的key
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^(?P[v1|v2]+)/test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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

REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1',            # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
'VERSION_PARAM': 'version'          # URL中获取值的key
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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. 基于主机名方法

如:www.sxzhongrui.com

ALLOWED_HOSTS = ['*']
REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1',  # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
'VERSION_PARAM': 'version'  # URL中获取值的key
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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

如:www.sxzhongrui.com/v1/users/

REST_FRAMEWORK = {
'DEFAULT_VERSION': 'v1',  # 默认版本
'ALLOWED_VERSIONS': ['v1', 'v2'],  # 允许的版本
'VERSION_PARAM': 'version'  # URL中获取值的key
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'^v1/', ([
url(r'test/', www.sxzhongrui.com_view(), name='test'),
], None, 'v1')),
url(r'^v2/', ([
url(r'test/', www.sxzhongrui.com_view(), name='test'),
], None, 'v2')),
]
#!/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. 全局使用

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

5. 解析器(parser) 

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

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

from django.conf.urls import url, include
from web.views.s5_parser import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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(www.sxzhongrui.com)
# application/x-www-form-urlencoded 或 multipart/form-data时,www.sxzhongrui.com中才有值
print(www.sxzhongrui.com)
print(request.FILES)
return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

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

from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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(www.sxzhongrui.com)
# application/x-www-form-urlencoded 或 multipart/form-data时,www.sxzhongrui.com中才有值
print(www.sxzhongrui.com)
print(request.FILES)
return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

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

from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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(www.sxzhongrui.com)
# application/x-www-form-urlencoded 或 multipart/form-data时,www.sxzhongrui.com中才有值
print(www.sxzhongrui.com)
print(request.FILES)
return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')




Title


d. 仅上传文件

from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/(?P[^/]+)', www.sxzhongrui.com_view(), name='test'),
]
#!/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(www.sxzhongrui.com)
# application/x-www-form-urlencoded 或 multipart/form-data时,www.sxzhongrui.com中才有值
print(www.sxzhongrui.com)
print(request.FILES)
return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')




Title


e. 同时多个Parser

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

from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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(www.sxzhongrui.com)
# application/x-www-form-urlencoded 或 multipart/form-data时,www.sxzhongrui.com中才有值
print(www.sxzhongrui.com)
print(request.FILES)
return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

f. 全局使用

REST_FRAMEWORK = {
'DEFAULT_PARSER_CLASSES':[
'rest_framework.parsers.JSONParser'
'rest_framework.parsers.FormParser'
'rest_framework.parsers.MultiPartParser'
]
}
from django.conf.urls import url, include
from web.views import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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(www.sxzhongrui.com)
# application/x-www-form-urlencoded 或 multipart/form-data时,www.sxzhongrui.com中才有值
print(www.sxzhongrui.com)
print(request.FILES)
return Response('POST请求,响应内容')
def put(self, request, *args, **kwargs):
return Response('PUT请求,响应内容')

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

6. 序列化

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

a. 自定义字段

from django.conf.urls import url, include
from web.views.s6_serializers import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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(www.sxzhongrui.com)
def post(self, request, *args, **kwargs):
# 验证,对请求发来的数据进行验证
ser = UserSerializer(data=www.sxzhongrui.com)
if www.sxzhongrui.com_valid():
print(ser.validated_data)
else:
print(ser.errors)
return Response('POST请求,响应内容')

b. 基于Model自动生成字段

from django.conf.urls import url, include
from web.views.s6_serializers import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view(), name='test'),
]
#!/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(www.sxzhongrui.com)
def post(self, request, *args, **kwargs):
# 验证,对请求发来的数据进行验证
print(www.sxzhongrui.com)
ser = ModelUserSerializer(data=www.sxzhongrui.com)
if www.sxzhongrui.com_valid():
print(ser.validated_data)
else:
print(ser.errors)
return Response('POST请求,响应内容')

c. 生成URL

from django.conf.urls import url, include
from web.views.s6_serializers import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view(), name='test'),
url(r'detail/(?P\d+)/', www.sxzhongrui.com_view(), name='detail'),
]
#!/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(www.sxzhongrui.com)
def post(self, request, *args, **kwargs):
# 验证,对请求发来的数据进行验证
print(www.sxzhongrui.com)
ser = ModelUserSerializer(data=www.sxzhongrui.com)
if www.sxzhongrui.com_valid():
print(ser.validated_data)
else:
print(ser.errors)
return Response('POST请求,响应内容')

7. 分页

a. 根据页码进行分页

from django.conf.urls import url, include
from rest_framework import routers
from web.views import s9_pagination
urlpatterns = [
url(r'^test/', s9_www.sxzhongrui.com_view()),
]
#!/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(www.sxzhongrui.com)
return response

b. 位置和个数进行分页

from django.conf.urls import url, include
from web.views import s9_pagination
urlpatterns = [
url(r'^test/', s9_www.sxzhongrui.com_view()),
]
#!/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(www.sxzhongrui.com)
return response

c. 游标分页

from django.conf.urls import url, include
from web.views import s9_pagination
urlpatterns = [
url(r'^test/', s9_www.sxzhongrui.com_view()),
]
#!/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(www.sxzhongrui.com)
return response

8. 路由系统

a. 自定义路由

from django.conf.urls import url, include
from web.views import s11_render
urlpatterns = [
url(r'^test/$', s11_www.sxzhongrui.com_view()),
url(r'^test\.(?P[a-z0-9]+)$', s11_www.sxzhongrui.com_view()),
url(r'^test/(?P[^/.]+)/$', s11_www.sxzhongrui.com_view()),
url(r'^test/(?P[^/.]+)\.(?P[a-z0-9]+)$', s11_www.sxzhongrui.com_view())
]
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('...')

b. 半自动路由

from django.conf.urls import url, include
from web.views import s10_generic
urlpatterns = [
url(r'^test/$', s10_www.sxzhongrui.com_view({'get': 'list', 'post': 'create'})),
url(r'^test/(?P\d+)/$', s10_www.sxzhongrui.com_view(
{'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]
#!/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

c. 全自动路由

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)),
]
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

9. 视图

a. GenericViewSet

from django.conf.urls import url, include
from web.views.s7_viewset import TestView
urlpatterns = [
url(r'test/', www.sxzhongrui.com_view({'get':'list'}), name='test'),
url(r'detail/(?P\d+)/', www.sxzhongrui.com_view({'get':'list'}), name='xxxx'),
]
#!/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

b. ModelViewSet(自定义URL)

from django.conf.urls import url, include
from web.views import s10_generic
urlpatterns = [
url(r'^test/$', s10_www.sxzhongrui.com_view({'get': 'list', 'post': 'create'})),
url(r'^test/(?P\d+)/$', s10_www.sxzhongrui.com_view(
{'get': 'retrieve', 'put': 'update', 'patch': 'partial_update', 'delete': 'destroy'})),
]
#!/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

c. ModelViewSet(rest framework路由)

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)),
]
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 = www.sxzhongrui.com
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

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

a. 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/ 
from django.conf.urls import url, include
from web.views import s11_render
urlpatterns = [
url(r'^test/$', s11_www.sxzhongrui.com_view()),
url(r'^test\.(?P[a-z0-9]+)', s11_www.sxzhongrui.com_view()),
]
#!/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(www.sxzhongrui.com)

b. 表格

访问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/ 
#!/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(www.sxzhongrui.com)

c. 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/ 
#!/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(www.sxzhongrui.com)

d. 自定义显示模板

访问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/ 
from django.conf.urls import url, include
from web.views import s11_render
urlpatterns = [
url(r'^test/$', s11_www.sxzhongrui.com_view()),
url(r'^test\.(?P[a-z0-9]+)', s11_www.sxzhongrui.com_view()),
]
#!/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(www.sxzhongrui.com, template_name='user_detail.html')




Title


{{ user }}
{{ pwd }}
{{ ut }}

e. 浏览器格式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/ 
#!/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(www.sxzhongrui.com, template_name='user_detail.html')

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

 

关闭

赞赏
返回顶部