django DRF


DjangoRestFramework

1. 安装:

pip install djangorestframework

2. restful规范:

2.1 API与用户通信协议,总是使用https协议(我们现在用的大部分都是http)

2.2 域名

  https://api.cainiao.com  尽量将API部署在专用域名(会存在跨域问题)

  https://cainiao.com/api/  API很简单(推荐使用)

2.3 版本

  URL,如:https://api.cainiao.com/v1/

  存在跨域问题咱不慌,请往这里看=>:https://www.cnblogs.com/xingxingnbsp/p/10644135.html

2.4 路径,将网络上的所有东西都看成是资源,均使用名词表示(可以使用复数)

  https://api.cainiao.com/v1/zoos

  https://api.cainiao.com/v1/animls

  https://api.cainiao.com/v1/employees

2.5 method(请求方式)

  GET : 从服务器取出资源(一项或多项)

  POST : 在服务器新建一个资源

  PUT : 在服务器更新资源(客户端提供改变后的完整资源)

  PATCH : 在服务器更新资源(客户端提供改变的属性)

  DELETE : 从服务器删除资源

2.6 过滤,通过在url上传参的形式传递搜索条件

  https://api.cainiao.com/v1/zoos?limit=10  : 指定返回记录的数量

  https://api.cainiao.com/v1/zoos?offset=10  : 指定返回记录的数量

  https://api.cainiao.com/v1/zoos?page=2&per_page=100  : 指定第几页,以及每页的记录数

  https://api.cainiao.com/v1/zoos?sortby=name&order=asc  : 指定返回结果按照哪个属性排序,以及排序规则

2.7 状态码

  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

2.8 错误处理

{ error:"lnvalid API key" }

 

2.9 返回结果,针对不同操作,服务器向用户返回的结果应该符合以下规范。

  GET/collection : 返回资源对象的列表(数组)

  GET/collection/response : 返回单个资源对象

  POST/collection : 返回新生成的资源对象

  PUT/collection/response : 返回完整的资源对象

  PATCH/collection/response :返回完整的资源对象

  DELETE/collection/response :返回一个空文档

2.10 Hypermedia API,RESTful API最好做到Hypermedia,即返回结果中提供链接,连向其他API方法,使得用户不查文档,也知道下一步应该做什么。

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

 3. 配置文件(settings.py)

# django rest framework配置
REST_FRAMEWORK = { # 解析器配置
    'DEFAULT_PARSER_CLASSES':[ 'rest_framework.parsers.JSONParser'
        'rest_framework.parsers.FormParser'
        'rest_framework.parsers.MultiPartParser' ] # 版本配置
    'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning", 'DEFAULT_VERSION': 'v1',                # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],        # 允许的版本
    'VERSION_PARAM': 'version'                 # URL中获取值的key
    
    # 用户登录认证
    'UNAUTHENTICATED_USER': None, 'UNAUTHENTICATED_TOKEN': None, "DEFAULT_AUTHENTICATION_CLASSES": ["web.utils.TestAuthentication",], # 用户权限验证
    "DEFAULT_PERMISSION_CLASSES": ["web.utils.TestPermission",], # 用户访问频率限制(匿名时用IP限制+登录时用Token限制)
   '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.模块详细介绍:

4.1 认证模块,权限模块:

4.1.1 用户url传入的token认证:

urls.py: from django.conf.urls import url, include from web.viewsimport TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ]
views.py:
from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptions token_list = [ 'sfsfss123kuf3j123', 'asijnfowerkkf9812', ] class TestAuthentication(BaseAuthentication): def authenticate(self, request): """ 注释001 """ val = request.query_params.get('token') if val not in token_list: raise exceptions.AuthenticationFailed("用户认证失败") return ('登录用户', '用户token') def authenticate_header(self, request): # 验证失败时,返回的响应头WWW-Authenticate对应的值 pass class TestView(APIView): authentication_classes = [TestAuthentication, ] permission_classes = [] def get(self, request, *args, **kwargs): print(request.user) print(request.auth) return Response('GET请求,响应内容') def post(self, request, *args, **kwargs): return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容')

4.1.2 请求头认证:

urls.py: from django.conf.urls import url, include from web.viewsimport TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptions token_list = [ 'sfsfss123kuf3j123', 'asijnfowerkkf9812', ] class TestAuthentication(BaseAuthentication): def authenticate(self, request): """ 注释001 """
            import base64 auth = request.META.get('HTTP_AUTHORIZATION', b'') if auth: auth = auth.encode('utf-8') auth = auth.split() if not auth or auth[0].lower() != b'basic': raise exceptions.AuthenticationFailed('验证失败') if len(auth) != 2: raise exceptions.AuthenticationFailed('验证失败') username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':') if username == 'alex' and password == '123': return ('登录用户', '用户token') else: raise exceptions.AuthenticationFailed('用户名或密码错误') def authenticate_header(self, request): return 'Basic realm=api'
                        
    class TestView(APIView): authentication_classes = [TestAuthentication, ] permission_classes = [] def get(self, request, *args, **kwargs): print(request.user) print(request.auth) return Response('GET请求,响应内容') def post(self, request, *args, **kwargs): return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容')

4.1.3 多个认证规则:

urls.py: from django.conf.urls import url, include from web.views.s2_auth import TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.request import Request from rest_framework import exceptions token_list = [ 'sfsfss123kuf3j123', 'asijnfowerkkf9812', ] class Test1Authentication(BaseAuthentication): def authenticate(self, request): """ 注释001 """
            import base64 auth = request.META.get('HTTP_AUTHORIZATION', b'') if auth: auth = auth.encode('utf-8') else: return None print(auth,'xxxx') auth = auth.split() if not auth or auth[0].lower() != b'basic': raise exceptions.AuthenticationFailed('验证失败') if len(auth) != 2: raise exceptions.AuthenticationFailed('验证失败') username, part, password = base64.b64decode(auth[1]).decode('utf-8').partition(':') if username == 'alex' and password == '123': return ('登录用户', '用户token') else: raise exceptions.AuthenticationFailed('用户名或密码错误') def authenticate_header(self, request): # return 'Basic realm=api'
            pass

    class Test2Authentication(BaseAuthentication): def authenticate(self, request): """ 注释001 """ val = request.query_params.get('token') if val not in token_list: raise exceptions.AuthenticationFailed("用户认证失败") return ('登录用户', '用户token') def authenticate_header(self, request): pass

    class TestView(APIView): authentication_classes = [Test1Authentication, Test2Authentication] permission_classes = [] def get(self, request, *args, **kwargs): print(request.user) print(request.auth) return Response('GET请求,响应内容') def post(self, request, *args, **kwargs): return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容')

4.1.4 认证和权限:

 

urls.py: from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.authentication import BaseAuthentication from rest_framework.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): """  注释001 """             val = request.query_params.get('token') if val not in token_list: raise exceptions.AuthenticationFailed("用户认证失败") return ('登录用户', '用户token') def authenticate_header(self, request): 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请求,响应内容')

 

4.1.5 全局使用:

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

 

 

4.1.6 基于django-rest-framework的JWT认证(推荐使用):

安装:

pip install djangorestframework-jwt

配置:

REST_FRAMEWORK = { 'DEFAULT_AUTHENTICATION_CLASSES': ( 'rest_framework_jwt.authentication.JSONWebTokenAuthentication', #新增 'rest_framework.authentication.SessionAuthentication', 'rest_framework.authentication.BasicAuthentication', ), } JWT_AUTH = {   #JWT_EXPIRATION_DELTA 指明token的有效期 'JWT_EXPIRATION_DELTA':datetime.timedelta(days=1),
}

 

使用:

from rest_framework_jwt.settings import api_settings jwt_payload_handler = api_settings.JWT_PAYLOAD_HANDLER jwt_encode_handler = api_settings.JWT_ENCODE_HANDLER payload = jwt_payload_handler(user) token = jwt_encode_handler(payload)

使用Django REST framework JWT进行用户登录:

from rest_framework_jwt.views import obtain_jwt_token urlpatterns = [ url(r'^authorizations/$', obtain_jwt_token), ]

4.2 用户访问次数/频率限制:

4.2.1 基于用户IP限制访问频率:

 

urls.py from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ] views.py: 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,当做请求者的唯一标识 """             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)

 

 

 

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

settings.py: REST_FRAMEWORK = { 'DEFAULT_THROTTLE_RATES': { 'test_scope': '10/m', }, } urls.py: from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ] views.py: 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): 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)

4.2.3 view中限制请求频率:

settings.py: REST_FRAMEWORK = { 'DEFAULT_THROTTLE_RATES': { 'xxxxxx': '10/m', }, } urls.py: from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ] views.py: # !/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import exceptions from rest_framework.throttling import ScopedRateThrottle # 继承 ScopedRateThrottle
    class TestThrottle(ScopedRateThrottle): def get_cache_key(self, request, view): """ 应该返回一个惟一的缓存键,该缓存键可用于节流。 必须覆盖。 如果请求不应该被节流,可以返回“None”。 """
            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)

 

4.3.4 匿名时用IP限制+登录时用Token限制:

settings.py: REST_FRAMEWORK = { 'UNAUTHENTICATED_USER': None, 'UNAUTHENTICATED_TOKEN': None, 'DEFAULT_THROTTLE_RATES': { 'luffy_anon': '10/m', 'luffy_user': '20/m', }, } urls.py: from django.conf.urls import url, include from web.views.s3_throttling import TestView urlpatterns = [ url(r'^test/', TestView.as_view()), ] views.py: 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请求,响应内容')

 

4.3.5 全局使用

settings.py: 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.3 版本控制:

4.3.1 基于url的get传参方式(如:/users?version=v1):

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

4.3.2 基于url的正则方式(如:/v1/users/):

 

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

 

4.3.3 基于 accept 请求头方式(如:Accept: application/json; version=1.0):

 

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

4.3.4 基于主机名方法(如:v1.example.com):

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

 

4.3.5  基于django路由系统的namespace(如:example.com/v1/users/):

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

 

4.3.6 全局使用:

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

 

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

4.4.1 仅处理请求头content-type为application/json的请求体:

 

urls.py: from django.conf.urls import url, include from web.views.s5_parser import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import JSONParser class TestView(APIView): parser_classes = [JSONParser, ] def post(self, request, *args, **kwargs): print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data) # application/x-www-form-urlencoded 或 multipart/form-data时, request.POST中才有值
            print(request.POST) print(request.FILES) return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容')

 

 

 

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

urls.py: from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import FormParser class TestView(APIView): parser_classes = [FormParser, ] def post(self, request, *args, **kwargs): print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data) # application/x-www-form-urlencoded 或 multipart/form-data时, request.POST中才有值
            print(request.POST) print(request.FILES) return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容')

 

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

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

 

4.4.4 仅上传文件:

urls.py: from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import FileUploadParser class TestView(APIView): parser_classes = [FileUploadParser, ] def post(self, request, filename, *args, **kwargs): print(filename) print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data) # application/x-www-form-urlencoded 或 multipart/form-data时, request.POST中才有值
            print(request.POST) print(request.FILES) return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容') upload.html: <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
    <form action="http://127.0.0.1:8000/test/f1.numbers" method="post" enctype="multipart/form-data">
        <input type="text" name="user" />
        <input type="file" name="img">
        <input type="submit" value="提交">
    </form>
    </body>
    </html>

 

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

urls.py: from django.conf.urls import url, include from web.views import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework.request import Request from rest_framework.parsers import JSONParser, FormParser, MultiPartParser class TestView(APIView): parser_classes = [JSONParser, FormParser, MultiPartParser, ] def post(self, request, *args, **kwargs): print(request.content_type) # 获取请求的值,并使用对应的JSONParser进行处理
            print(request.data) # application/x-www-form-urlencoded 或 multipart/form-data时, request.POST中才有值
            print(request.POST) print(request.FILES) return Response('POST请求,响应内容') def put(self, request, *args, **kwargs): return Response('PUT请求,响应内容')

4.4.6 全局使用:

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

 

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

4.5.1 自定义字段:

urls.py: from django.conf.urls import url, include from web.views.s6_serializers import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from .. import models class PasswordValidator(object): def __init__(self, base): self.base = base def __call__(self, value): if value != self.base: message = 'This field must be %s.' % self.base raise serializers.ValidationError(message) def set_context(self, serializer_field): """ This hook is called by the serializer instance, prior to the validation call being made. """
            # 执行验证之前调用,serializer_fields是当前字段对象
            pass
    
    
    class UserSerializer(serializers.Serializer): ut_title = serializers.CharField(source='ut.title') user = serializers.CharField(min_length=6) pwd = serializers.CharField(error_messages={'required': '密码不能为空'}, validators=[PasswordValidator('666')]) class TestView(APIView): def get(self, request, *args, **kwargs): # 序列化,将数据库查询字段序列化为字典
            data_list = models.UserInfo.objects.all() ser = UserSerializer(instance=data_list, many=True) #
            # obj = models.UserInfo.objects.all().first()
            # ser = UserSerializer(instance=obj, many=False)
            return Response(ser.data) def post(self, request, *args, **kwargs): # 验证,对请求发来的数据进行验证
            ser = UserSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data) else: print(ser.errors) return Response('POST请求,响应内容')

 

4.5.2 基于Model自动生成字段:

urls.py: from django.conf.urls import url, include from web.views.s6_serializers import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from .. import models class PasswordValidator(object): def __init__(self, base): self.base = str(base) def __call__(self, value): if value != self.base: message = 'This field must be %s.' % self.base raise serializers.ValidationError(message) def set_context(self, serializer_field): """ This hook is called by the serializer instance, prior to the validation call being made. """
            # 执行验证之前调用,serializer_fields是当前字段对象
            pass

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

    class TestView(APIView): def get(self, request, *args, **kwargs): # 序列化,将数据库查询字段序列化为字典
            data_list = models.UserInfo.objects.all() ser = ModelUserSerializer(instance=data_list, many=True) #
            # obj = models.UserInfo.objects.all().first()
            # ser = UserSerializer(instance=obj, many=False)
            return Response(ser.data) def post(self, request, *args, **kwargs): # 验证,对请求发来的数据进行验证
            print(request.data) ser = ModelUserSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data) else: print(ser.errors) return Response('POST请求,响应内容')

 

4.5.3 生成URL:

urls.py: from django.conf.urls import url, include from web.views.s6_serializers import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), url(r'detail/(?P<pk>\d+)/', TestView.as_view(), name='detail'), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from .. import models class PasswordValidator(object): def __init__(self, base): self.base = str(base) def __call__(self, value): if value != self.base: message = 'This field must be %s.' % self.base raise serializers.ValidationError(message) def set_context(self, serializer_field): """ This hook is called by the serializer instance, prior to the validation call being made. """
            # 执行验证之前调用,serializer_fields是当前字段对象
            pass

    class ModelUserSerializer(serializers.ModelSerializer): ut = serializers.HyperlinkedIdentityField(view_name='detail') class Meta: model = models.UserInfo fields = "__all__" extra_kwargs = { 'user': {'min_length': 6}, 'pwd': {'validators': [PasswordValidator(666),]}, } class TestView(APIView): def get(self, request, *args, **kwargs): # 序列化,将数据库查询字段序列化为字典
            data_list = models.UserInfo.objects.all() ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request}) #
            # obj = models.UserInfo.objects.all().first()
            # ser = UserSerializer(instance=obj, many=False)
            return Response(ser.data) def post(self, request, *args, **kwargs): # 验证,对请求发来的数据进行验证
            print(request.data) ser = ModelUserSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data) else: print(ser.errors) return Response('POST请求,响应内容')

4.5.4 自动生成URL:

urls.py: from django.conf.urls import url, include from web.views.s6_serializers import TestView urlpatterns = [ url(r'test/', TestView.as_view(), name='test'), url(r'detail/(?P<pk>\d+)/', TestView.as_view(), name='xxxx'), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from .. import models class PasswordValidator(object): def __init__(self, base): self.base = str(base) def __call__(self, value): if value != self.base: message = 'This field must be %s.' % self.base raise serializers.ValidationError(message) def set_context(self, serializer_field): """ This hook is called by the serializer instance, prior to the validation call being made. """
            # 执行验证之前调用,serializer_fields是当前字段对象
            pass

    class ModelUserSerializer(serializers.HyperlinkedModelSerializer): ll = serializers.HyperlinkedIdentityField(view_name='xxxx') tt = serializers.CharField(required=False) class Meta: model = models.UserInfo fields = "__all__" list_serializer_class = serializers.ListSerializer extra_kwargs = { 'user': {'min_length': 6}, 'pwd': {'validators': [PasswordValidator(666), ]}, 'url': {'view_name': 'xxxx'}, 'ut': {'view_name': 'xxxx'}, } class TestView(APIView): def get(self, request, *args, **kwargs): # # 序列化,将数据库查询字段序列化为字典
            data_list = models.UserInfo.objects.all() ser = ModelUserSerializer(instance=data_list, many=True, context={'request': request}) # # 如果Many=True
            # # 或
            # # obj = models.UserInfo.objects.all().first()
            # # ser = UserSerializer(instance=obj, many=False)
            return Response(ser.data) def post(self, request, *args, **kwargs): # 验证,对请求发来的数据进行验证
            print(request.data) ser = ModelUserSerializer(data=request.data) if ser.is_valid(): print(ser.validated_data) else: print(ser.errors) return Response('POST请求,响应内容')

 

4.6 分页:

4.6.1 根据页码进行分页:

urls.py: from django.conf.urls import url, include from rest_framework import routers from web.views import s9_pagination urlpatterns = [ url(r'^test/', s9_pagination.UserViewSet.as_view()), ] views.py: from rest_framework.views import APIView from rest_framework import serializers from .. import models from rest_framework.pagination import PageNumberPagination class StandardResultsSetPagination(PageNumberPagination): # 默认每页显示的数据条数
        page_size = 1
        # 获取URL参数中设置的每页显示数据条数
        page_size_query_param = 'page_size'
        # 获取URL参数中传入的页码key
        page_query_param = 'page'
        # 最大支持的每页显示的数据条数
        max_page_size = 1

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

    class UserViewSet(APIView): def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().order_by('-id') # 实例化分页对象,获取数据库中的分页数据
            paginator = StandardResultsSetPagination() page_user_list = paginator.paginate_queryset(user_list, self.request, view=self) # 序列化对象
            serializer = UserSerializer(page_user_list, many=True) # 生成分页和数据
            response = paginator.get_paginated_response(serializer.data) return response

 

4.6.2 位置和个数进行分页:

urls.py: from django.conf.urls import url, include from web.views import s9_pagination urlpatterns = [ url(r'^test/', s9_pagination.UserViewSet.as_view()), ] views.py: from rest_framework.views import APIView from rest_framework import serializers from .. import models from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination class StandardResultsSetPagination(LimitOffsetPagination): # 默认每页显示的数据条数
        default_limit = 10
        # URL中传入的显示数据条数的参数
        limit_query_param = 'limit'
        # URL中传入的数据位置的参数
        offset_query_param = 'offset'
        # 最大每页显得条数
        max_limit = None class UserSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__"

    class UserViewSet(APIView): def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().order_by('-id') # 实例化分页对象,获取数据库中的分页数据
            paginator = StandardResultsSetPagination() page_user_list = paginator.paginate_queryset(user_list, self.request, view=self) # 序列化对象
            serializer = UserSerializer(page_user_list, many=True) # 生成分页和数据
            response = paginator.get_paginated_response(serializer.data) return response

 

4.6.3 游标分页:

urls.py: from django.conf.urls import url, include from web.views import s9_pagination urlpatterns = [ url(r'^test/', s9_pagination.UserViewSet.as_view()), ] views.py: from rest_framework.views import APIView from rest_framework import serializers from .. import models from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination class StandardResultsSetPagination(CursorPagination): # URL传入的游标参数
        cursor_query_param = 'cursor'
        # 默认每页显示的数据条数
        page_size = 2
        # URL传入的每页显示条数的参数
        page_size_query_param = 'page_size'
        # 每页显示数据最大条数
        max_page_size = 1000
        # 根据ID从大到小排列
        ordering = "id"
    
    
    class UserSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__"
    
    
    class UserViewSet(APIView): def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().order_by('-id') # 实例化分页对象,获取数据库中的分页数据
            paginator = StandardResultsSetPagination() page_user_list = paginator.paginate_queryset(user_list, self.request, view=self) # 序列化对象
            serializer = UserSerializer(page_user_list, many=True) # 生成分页和数据
            response = paginator.get_paginated_response(serializer.data) return response

 

4.7 路由系统:

4.7.1 自定义路由:

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

4.7.2 半自动路由:

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

4.7.3 全自动路由:

urls.py: 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)), ] views.py: 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

 

4.8 视图:

4.8.1 GenericViewSet:

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

4.8.2 ModelViewSet(自定义URL):

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

 

4.8.3 ModelViewSet(rest framework路由):

urls.py: 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)), ] views.py: from rest_framework import viewsets from rest_framework import serializers class UserSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = models.User fields = ('url', 'username', 'email', 'groups') class GroupSerializer(serializers.HyperlinkedModelSerializer): class Meta: model = models.Group fields = ('url', 'name') class UserViewSet(viewsets.ModelViewSet): """ API endpoint that allows users to be viewed or edited. """ queryset = User.objects.all().order_by('-date_joined') serializer_class = UserSerializer class GroupViewSet(viewsets.ModelViewSet): """ API endpoint that allows groups to be viewed or edited. """ queryset = Group.objects.all() serializer_class = GroupSerializer

4.9 渲染器:

4.9.1 简介:

  根据 用户请求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

4.9.2 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/ 

urls.py: from django.conf.urls import url, include from web.views import s11_render urlpatterns = [ url(r'^test/$', s11_render.TestView.as_view()), url(r'^test\.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from rest_framework.renderers import JSONRenderer from .. import models class TestSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__"
    
    
    class TestView(APIView): renderer_classes = [JSONRenderer, ] def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all() ser = TestSerializer(instance=user_list, many=True) return Response(ser.data)

 

4.9.3 表格:

  访问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/ 

views.py: #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from rest_framework.renderers import AdminRenderer from .. import models class TestSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__"

    class TestView(APIView): renderer_classes = [AdminRenderer, ] def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all() ser = TestSerializer(instance=user_list, many=True) return Response(ser.data)

 

4.9.4 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/ 

views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from rest_framework.renderers import JSONRenderer from rest_framework.renderers import AdminRenderer from rest_framework.renderers import HTMLFormRenderer from .. import models class TestSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__"

    class TestView(APIView): renderer_classes = [HTMLFormRenderer, ] def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().first() ser = TestSerializer(instance=user_list, many=False) return Response(ser.data)

 

4.9.5 自定义显示模板:

  访问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/

urls.py: from django.conf.urls import url, include from web.views import s11_render urlpatterns = [ url(r'^test/$', s11_render.TestView.as_view()), url(r'^test\.(?P<format>[a-z0-9]+)', s11_render.TestView.as_view()), ] views.py: from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from rest_framework.renderers import TemplateHTMLRenderer from .. import models class TestSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__"
    
    
    class TestView(APIView): renderer_classes = [TemplateHTMLRenderer, ] def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().first() ser = TestSerializer(instance=user_list, many=False) return Response(ser.data, template_name='user_detail.html') userdetail.html: <!DOCTYPE html>
    <html lang = "en">
    <head>
        <meta charset = "UTF-8">
        <title> Title </title>
    </head>
    <body> {{user}} {{pwd}} {{ut}} </body>
    </html>

4.9.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/ 

views.py: #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    from rest_framework.views import APIView from rest_framework.response import Response from rest_framework import serializers from rest_framework.renderers import JSONRenderer from rest_framework.renderers import BrowsableAPIRenderer from .. import models class TestSerializer(serializers.ModelSerializer): class Meta: model = models.UserInfo fields = "__all__"

    class CustomBrowsableAPIRenderer(BrowsableAPIRenderer): def get_default_renderer(self, view): return JSONRenderer() class TestView(APIView): renderer_classes = [CustomBrowsableAPIRenderer, ] def get(self, request, *args, **kwargs): user_list = models.UserInfo.objects.all().first() ser = TestSerializer(instance=user_list, many=False) return Response(ser.data, template_name='user_detail.html')

 

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

 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM