Django Rest Framework进阶二

一、版本

版本控制:当程序越来越大,后期需要再加入一些功能或者进行二次开发时就需要加上版本号了。

之前我们在没有接触rest_framework之前一般是以下这种方式来实现的

class UserView(APIView):
    def get(self,request,*args,**kwargs):
        version = request.query_params.get('version')
        print(version)
        if version=='v1':
            #如果版本是v1
            ret = {
                'code':111,
                'msg':'版本一的内容'
            }

        elif version=='v2':
            # 如果是v2
            ret = {
                'code': 112,
                'msg': '版本二的内容'
            }
        else:
            ret = {
                'code': 0,
                'msg': '不支持其他版本'
            }
        return Response(ret) 

现在我们可以用rest_framework来实现,主要有两种方式

方式一:基于url

 #基于url传参的形式
     versioning_class = QueryParameterVersioning
    #http://127.0.0.1:8080/api/users/?version=v2
    
#基于url的形式
  versioning_class = URLPathVersioning
  #http://127.0.0.1:8080/api/v1/users/

具体操作

REST_FRAMEWORK = {
     'DEFAULT_VERSION': 'v1',  #默认的版本
     'ALLOWED_VERSIONS': ['v1','v2'],  #允许的版本
     'VERSION_PARAM': 'version',
 }
配置
1 from django.conf.urls import url,include
2 from django.contrib import admin
3 
4 
5 urlpatterns = [
6     url(r'^admin/', admin.site.urls),
7     url(r'^api/(?P<version>[v1|v2]+)/', include('api.urls'), name='users-list'),
8 ]
urls.py
1 from api import views
2 urlpatterns = [
3     # url(r'^users/', views.UserView.as_view()),
4     url(r'^users/', views.UserView1.as_view()),
5 
6 ]
urls
class UserView1(APIView):
    #基于url传参的形式
    # versioning_class = QueryParameterVersioning
    #http://127.0.0.1:8080/api/users/?version=v2

    #基于url的形式
    #http://127.0.0.1:8080/api/v1/users/
    versioning_class = URLPathVersioning
    def get(self,request,*args,**kwargs):
        # self.dispatch
        print(request.version)  #打印的是版本
        print(request.versioning_scheme)  #打印的是对象
        if request.version=='v2':
            return Response('我是版本二')
        elif request.version=='v1':
            return Response('我是版本一')
        else:
            return Response('...')

views.py
view.py

注意:配置

REST_FRAMEWORK = {
                'VERSION_PARAM':'version',
                'DEFAULT_VERSION':'v1',
                'ALLOWED_VERSIONS':['v1','v2'],
                # 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning" 
           #如果加上这个配置就不用versioning_class = QueryParameterVersioning这样在指定了,
           'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning" } 

补充:restful提供的反向生成(http://127.0.0.1:8080/api/v1/users/)

#urls.py 
#分发路由
urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^api/(?P<version>[v1|v2]+)/', include('api.urls')),
]

#api.urls.py
urlpatterns = [
    url(r'^users/', views.UserView1.as_view(), name='users-list'),
]

#views.py 
导入类
from rest_framework.reverse import reverse
url = request.versioning_scheme.reverse(viewname='users-list',request=request)
        print(url)

restfoamework反向解析
restfoamework反向解析

我们用django实现的,当前版本不一样的时候可以用这种方式。

from django.urls import reverse
        url = reverse(viewname='users-list',kwargs={'version':'v2'}) #指定的是v2就是v2,当你路径中输入v1的时候还是v2的路径
        print(url) #/api/v2/users/

方式二:基于子域名传参

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

            urlpatterns = [
                url(r'^users/', views.UsersView.as_view(),name='u'),
            ]
            
            
            class UsersView(APIView):
                
                def get(self,request,*args,**kwargs):
                    self.dispatch
                    print(request.version) # QueryParameterVersioning().detemiin_version()
                    print(request.versioning_scheme) # QueryParameterVersioning()

            
            REST_FRAMEWORK = {
                'VERSION_PARAM':'version',
                'DEFAULT_VERSION':'v1',
                'ALLOWED_VERSIONS':['v1','v2'],
                'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"
            }
            
            # C:WindowsSystem32driversetc
            # vim /etc/hosts
            127.0.0.1    v1.luffy.com
            127.0.0.1    v2.luffy.com
            
            #配置ALLOWED_HOSTS = ['*']

基于子域名传参
基于子域名传参

二、解析器

用处:request.data取值的时候才会用到

对请求的数据进行解析:是针对请求体进行解析的。表示服务器可以解析的数据格式的种类

django中的发送请求

#如果是这样的格式发送的数据,在POST里面有值
Content-Type: application/url-encoding.....
    request.body
    request.POST
    
#如果是发送的json的格式,在POST里面是没有值的,在body里面有值,可通过decode,然后loads取值        
Content-Type: application/json.....
    request.body
    request.POST

为了这种情况下每次都要decode,loads,显得麻烦,所以才有的解析器。弥补了django的缺点

客户端:
            Content-Type: application/json
            '{"name":"alex","age":123}'
        
        服务端接收:
            读取客户端发送的Content-Type的值 application/json
            
            parser_classes = [JSONParser,FormParser]  #表示服务器可以解析的数据格式的种类
            media_type_list = ['application/json','application/x-www-form-urlencoded']
        
            如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
            如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据
        
        
        配置:
            单视图:
            class UsersView(APIView):
                parser_classes = [JSONParser,]
                
            全局配置:
                REST_FRAMEWORK = {
                    'VERSION_PARAM':'version',
                    'DEFAULT_VERSION':'v1',
                    'ALLOWED_VERSIONS':['v1','v2'],
                    # 'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.HostNameVersioning"
                    'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
                    'DEFAULT_PARSER_CLASSES':[
                        'rest_framework.parsers.JSONParser',
                        'rest_framework.parsers.FormParser',
                    ]
                }
                
                class UserView(APIView):
                    def get(self,request,*args,**kwargs):
                        return Response('ok')
                    def post(self,request,*args,**kwargs):
                        print(request.data)  #以后取值就在这里面去取值
                        return Response('...')
具体讲解

上传文件

1 from django.conf.urls import url, include
2 from web.views import TestView
3 
4 urlpatterns = [
5     url(r'test/(?P<filename>[^/]+)', TestView.as_view(), name='test'),
6 ]
urls
#!/usr/bin/env python
# -*- coding:utf-8 -*-
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.request import Request
from rest_framework.parsers import FileUploadParser


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

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

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

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

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

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

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

upload.html
upload.html

全局使用

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

}
settings.py
原文地址:https://www.cnblogs.com/moning/p/8432994.html