(了解)rest_framework之版本控制, 响应器, url控制器

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了(了解)rest_framework之版本控制, 响应器, url控制器相关的知识,希望对你有一定的参考价值。

参考技术A 本文均为了解点

掌握的:URLPathVersioning

-局部使用:
​ versioning_class = URLPathVersioning

-全局使用:

路由配置:

在视图类中的request对象中,就可以取出版本号

反向解析:

rest_framework中用Response返回数据时, 默认返回给浏览器的是一个好看的页面,例如

url为: http://127.0.0.1:8000/book/ 时, 返回的是页面

如果不要返回页面, 而是只返回数据需要这样

http://127.0.0.1:8000/book/?format=json

自己指定返回啥

Python之Django rest_Framework

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

rest_Framework的规范:

    按顺序:它的method的不同,原来没有考虑,原来是url区分,现在通过method来区分,method的不同提交方式不同,紧接着一般是面向资源的就是把url变成名词,接下就是返回值,以前没有考虑状态码,现在有考虑状态码。(一般有get,post方法,还有put,delete等方法)

 

一、Django rest_Framework框架

   ----为什么用Django rest_Framework框架?

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

  ----设计比较好

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

二、Django rest_Framework原理?

        先开始在路由,路由.as_view:

点击as_view

           

请求进来,走完以上,才走self.dispatch()

self.dispatch()流程如下地址:http://www.cnblogs.com/mengqingjian/p/8419563.html 

三、版本

a.根据url的不同来来操作,版本控制

先在setting中注册

 

from django.conf.urls import url,include
from django.contrib import admin

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

 

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"
}
settings.py配置
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BasicAuthentication
from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning,HostNameVersioning
from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer

class UsersView(APIView):
    # 基于url传参
    # versioning_class = QueryParameterVersioning

    # 基于URL http://127.0.0.1:8001/api/v2/users/
    # versioning_class = URLPathVersioning

    # 基于子域名 http://v1.luffy.com/users/
    # versioning_class = HostNameVersioning


    def get(self,request,*args,**kwargs):
        self.dispatch
        # print(request.version) # QueryParameterVersioning().detemiin_version()
        # print(request.versioning_scheme) # QueryParameterVersioning()

        # 当前版本一样的URL
        # url = request.versioning_scheme.reverse(viewname=\'u\',request=request)
        # print(url)

        # 当前版本不一样的URL
        # from django.urls import reverse
        # url = reverse(viewname=\'u\',kwargs={\'version\':\'v2\'})
        # print(url)


        return Response(\'...\')
views.py
from django.conf.urls import url,include
from . import views
urlpatterns = [
    url(r\'^users/\', views.UsersView.as_view(),name=\'u\'),
]
url.py -----和view在一个APP中的路由

b、

 HostName
            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:\\Windows\\System32\\drivers\\etc
            # vim /etc/hosts
            127.0.0.1    v1.luffy.com
            127.0.0.1    v2.luffy.com

四、rest framework解析器

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

Content-Type: application/url-encoding.....
            request.body
            request.POST
            
            Content-Type: application/json.....
            request.body
            request.POST
        
        客户端:
            Content-Type: application/json
            \'{"name":"alex","age":123}\'
        
        服务端接收:
            读取客户端发送的Content-Type的值 application/json
            
            parser_classes = [JSONParser,]
            media_type_list = [\'application/json\',]
        
            如果客户端的Content-Type的值和 application/json 匹配:JSONParser处理数据
            如果客户端的Content-Type的值和 application/x-www-form-urlencoded 匹配:FormParser处理数据
        
        
        配置:
            单视图:
            class UsersView(APIView):
                parser_classes = [JSONParser,]
                
            全局配置:
                REST_FRAMEWORK = {
                    \'VERSION_PARAM\':\'version\',
                    \'DEFAULT_VERSION\':\'v1\',
                    \'ALLOWED_VERSIONS\':[\'v1\',\'v2\'],
                    # \'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.HostNameVersioning"
                    \'DEFAULT_VERSIONING_CLASS\':"rest_framework.versioning.URLPathVersioning",
                    \'DEFAULT_PARSER_CLASSES\':[
                        \'rest_framework.parsers.JSONParser\',
                        \'rest_framework.parsers.FormParser\',
                    ]
                }
from django.conf.urls import url,include
from django.contrib import admin

urlpatterns = [
    #url(r\'^admin/\', admin.site.urls),
    url(r\'^api/(?P<version>[v1|v2]+)/\', include(\'api.urls\')),
    # url(r\'^api/\', include(\'api.urls\')),
    url(r\'^backend/\', include(\'backend.urls\')),
]
url.py
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\',
    ]
}
setting.py
from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework.authentication import BasicAuthentication
from rest_framework.versioning import QueryParameterVersioning,URLPathVersioning,HostNameVersioning
from rest_framework.renderers import BrowsableAPIRenderer,JSONRenderer
from rest_framework.parsers import JSONParser,FormParser
from rest_framework.request import Request
class UsersView(APIView):
    def get(self,request,*args,**kwargs):
        self.dispatch
        return Response(\'...\')

    def post(self,request,*args,**kwargs):
        # # application/json
        # print(request._request.body) # b"xxxxx"   decode()   json.loads
        # print(request._request.POST) # 无
        #
        # # www-form-url-encode
        # print(request._request.body)
        # print(request._request.POST)
        # print(request.data)

        # print(request.POST)
        # print(request.FILES)

        request.data
        return Response(\'...\')
views.py
from django.conf.urls import url,include
from . import views
urlpatterns = [
    url(r\'^users/\', views.UsersView.as_view(),name=\'u\'),
]
url.py 和view一个APP下的文件

五、 rest framework序列化+Form

序列化:
        对象 -> 字符串 序列化
        字符串 -> 对象 反序列化
目的:
        解决QuerySet序列化问题

序列化:

a、基本操作

 

class UsersSerializer(serializers.Serializer):
                    name = serializers.CharField()
                    pwd = serializers.CharField()
            
                        
                class UsersView(APIView):
                    def get(self,request,*args,**kwargs):
                        self.dispatch
                        # 方式一:
                        # user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
                        # return Response(user_list)

                        # 方式二之多对象
                        # user_list = models.UserInfo.objects.all()
                        # ser = UsersSerializer(instance=user_list,many=True)
                        # return Response(ser.data)

                        # 方式二之单对象
                        user = models.UserInfo.objects.all().first()
                        ser = UsersSerializer(instance=user, many=False)
                        return Response(ser.data)

 

b、跨表

class UsersSerializer(serializers.Serializer):
                    name = serializers.CharField()
                    pwd = serializers.CharField()
                    group_id = serializers.CharField()
                    xxxx = serializers.CharField(source="group.title")
                    x1 = serializers.CharField(source="group.mu.name")



                class UsersView(APIView):
                    def get(self,request,*args,**kwargs):
                        self.dispatch
                        # 方式一:
                        # user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
                        # return Response(user_list)

                        # 方式二之多对象
                        user_list = models.UserInfo.objects.all()
                        ser = UsersSerializer(instance=user_list,many=True)
                        return Response(ser.data)

c、复杂序列化

解决方案一:
                    class MyCharField(serializers.CharField):

                        def to_representation(self, value):
                            data_list = []
                            for row in value:
                                data_list.append(row.name)
                            return data_list

                    class UsersSerializer(serializers.Serializer):
                        name = serializers.CharField() # obj.name
                        pwd = serializers.CharField()  # obj.pwd
                        group_id = serializers.CharField() # obj.group_id
                        xxxx = serializers.CharField(source="group.title") # obj.group.title
                        x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
                        # x2 = serializers.CharField(source="roles.all") # obj.mu.name
                        x2 = MyCharField(source="roles.all") # obj.mu.name
    
                解决方案二:
                    class MyCharField(serializers.CharField):
                        def to_representation(self, value):
                            return {\'id\':value.pk, \'name\':value.name}

                    class UsersSerializer(serializers.Serializer):
                        name = serializers.CharField() # obj.name
                        pwd = serializers.CharField()  # obj.pwd
                        group_id = serializers.CharField() # obj.group_id
                        xxxx = serializers.CharField(source="group.title") # obj.group.title
                        x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
                        # x2 = serializers.CharField(source="roles.all") # obj.mu.name
                        x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name

                解决方案三(*):
                    class UsersSerializer(serializers.Serializer):
                        name = serializers.CharField() # obj.name
                        pwd = serializers.CharField()  # obj.pwd
                        group_id = serializers.CharField() # obj.group_id
                        xxxx = serializers.CharField(source="group.title") # obj.group.title
                        x1 = serializers.CharField(source="group.mu.name") # obj.mu.name
                        # x2 = serializers.CharField(source="roles.all") # obj.mu.name
                        # x2 = serializers.ListField(child=MyCharField(),source="roles.all") # obj.mu.name
                        x2 = serializers.SerializerMethodField()

                        def get_x2(self,obj):
                            obj.roles.all()
                            role_list = obj.roles.filter(id__gt=1)
                            data_list = []
                            for row in role_list:
                                data_list.append({\'pk\':row.pk,\'name\':row.name})
                            return data_list

以上三种都是使用相同的视图:

class UsersView(APIView):
                        def get(self,request,*args,**kwargs):
                            self.dispatch
                            # 方式一:
                            # user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
                            # return Response(user_list)

                            # 方式二之多对象
                            user_list = models.UserInfo.objects.all()
                            # [obj1,obj2,obj3]
                            ser = UsersSerializer(instance=user_list,many=True)
                            return Response(ser.data)
d. 基于Model   
class UsersSerializer(serializers.ModelSerializer):
                    class Meta:
                        model = models.UserInfo
                        fields = "__all__"
                        # fields = [\'name\', \'pwd\',\'group\']
                        depth = 1


                class UsersView(APIView):
                    def get(self,request,*args,**kwargs):
                        self.dispatch
                        # 方式一:
                        # user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
                        # return Response(user_list)

                        # 方式二之多对象
                        user_list = models.UserInfo.objects.all()
                        # [obj1,obj2,obj3]
                        ser = UsersSerializer(instance=user_list,many=True)
                        return Response(ser.data)

e. 生成URL

class UsersSerializer(serializers.ModelSerializer):
                    group = serializers.HyperlinkedIdentityField(view_name=\'detail\')
                    class Meta:
                        model = models.UserInfo
                        fields = "__all__"
                        fields = [\'name\', \'pwd\',\'group\']
                        depth = 1


                class UsersView(APIView):
                    def get(self,request,*args,**kwargs):
                        self.dispatch
                        # 方式一:
                        # user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
                        # return Response(user_list)

                        # 方式二之多对象
                        user_list = models.UserInfo.objects.all()
                        # [obj1,obj2,obj3]
                        ser = UsersSerializer(instance=user_list,many=True,context={\'request\':request})
                        return Response(ser.data)

f. 全局生成URL

class UsersSerializer(serializers.HyperlinkedModelSerializer):
                    class Meta:
                        model = models.UserInfo
                        fields = "__all__"

                        # fields = [\'id\',\'name\',\'pwd\']

                class UsersView(APIView):
                    def get(self,request,*args,**kwargs):
                        self.dispatch
                        # 方式一:
                        # user_list = models.UserInfo.objects.all().values(\'name\',\'pwd\',\'group__id\',"group__title")
                        # return Response(user_list)

                        # 方式二之多对象
                        user_list = models.UserInfo.objects.all()
                        # [obj1,obj2,obj3]
                        ser = UsersSerializer(instance=user_list,many=True,context={\'request\':request})
                        return Response(ser.data)

请求数据验证:

a、

 

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

                    def __call__(self, value):
                        if value != self.base:
                            message = \'用户输入的值必须是 %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 UsersSerializer(serializers.Serializer):
                        name = serializers.CharField(min_length=6)
                        pwd = serializers.CharField(error_messages={\'required\': \'密码不能为空\'}, validators=[PasswordValidator(\'666\')])

 

b、

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

                    def __call__(self, value):
                        if value != self.base:
                            message = \'用户输入的值必须是 %s.\' % self.base
                            raise serializers.ValidationError(message)

                    def set_context(self, serializer_field):
                        """版本,认证,权限

rest_framework:url控制

Django框架深入了解_04(DRF之url控制解析器响应器版本控制分页)

Django之REST_FRAMEWORK 认证组件

Python之Django rest_Framework

python之Django rest_framework