• django rest framework组件下的详细功能的实现


    Django Rest Framework框架组件的执行流程

    rest framework组件为我们提供了下面的这些功能:
    按照HTTP请求的生命周期去记; 先是进入路由,在视图,进入dispatch()里面,然
    后提供的是版本,权限,认证,频率,然后从 解析器()里面取数据,再序列化,分页,渲染器。
    

    1.认证和授权

    a. 用户url传入的token认证(作为url的参数传入)

    from django.conf.urls import url, include
    from web.viewsimport TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
    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
    from .models import *
    
    
    class TokenAuth(BaseAuthentication):
    	def authenticate(self, request):
    		token = request.GET.get("token")
    		# request.query_params  ---> request.GET
    		token_obj = Token.objects.filter(token=token).first()
    		if not token_obj:
    			raise exceptions.AuthenticationFailed("验证失败123!")
    		else:
    			return token_obj.user, token_obj.token
    		# 返回一个元组 request.user, request.auth
    
    	# def authenticate_header(self, request):
    	#     pass
    	# 只是我们继承了BaseAuthentication的认证组件 就不用写了。
    
    
    class TestView(APIView):
        authentication_classes = [TokenAuth, ]
        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请求,响应内容')
    
    
    views.py
    

    认证和权限

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_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
    from .models import *
    
    
    class TokenAuth(BaseAuthentication):
    	def authenticate(self, request):
    		token = request.GET.get("token")
    		# request.query_params  ---> request.GET
    		token_obj = Token.objects.filter(token=token).first()
    		if not token_obj:
    			raise exceptions.AuthenticationFailed("验证失败123!")
    		else:
    			return token_obj.user.pk, token_obj.token
    		# 返回一个元组 request.user, request.auth
    
    	# def authenticate_header(self, request):
    	#     pass
    	# 只是我们继承了BaseAuthentication的认证组件 就不用写了。
    
    class SVIPPermisson(BasePermission):
    	message = "没有SVIP权限"  # 错误信息
    
    	def has_permission(self, request, view):
    		if request.user == 1:    # request.user.pk 是从认证组件里面取的
    			return True
    		else:
    			return False    #没有权限
    
    
    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请求,响应内容')
    
    
    
    views.py
    

    全局使用权限和认证,就需要在settings里面去配置全局信息。

    REST_FRAMEWORK = {
        "DEFAULT_AUTHENTICATION_CLASSES": [
            "web.utils.TestAuthentication",
        ],
        "DEFAULT_PERMISSION_CLASSES": [
            "web.utils.TestPermission",
        ],
    }
    
    settings.py
    

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

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

    这种方法是无法控制的,因为用户可以换代理IP,所以没有完全的限制。

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_view()),
    ]
    
    urls.py
    
    #!/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:               #判断当前IP的访问的次数(通过时间戳的数量)
                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] 
            #last_time 就是代表最长时间后才可以继续访问。
            min_time = RECORD[self.ident][-1]   
             #列表中最后一个是最小的时间,当最小的时间失效后就可以访问了。
            now = self.ctime()
            return int(60 + min_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)
    
    views.py                
    

     

    b. 基于用户IP显示访问频率(利于Django缓存)常用的  

    REST_FRAMEWORK = {
        'DEFAULT_THROTTLE_RATES': {
            'test_scope': '10/m',
        },
    }  

     

    在源码中

     num, period = rate.split('/')
            num_requests = int(num)
            duration = {'s': 1, 'm': 60, 'h': 3600, 'd': 86400}[period[0]]
            return (num_requests, duration)
    

    即通过/分割,前面是允许访问的次数,后面是时间。

    即在60s内可以访问的次数为10次

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'^test/', TestView.as_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)
    
    views.py
    

      

     如何实现的访问频率控制?
    
    		访问频率控制的原理:
    			用户进来时候,把它的访问时间记录全部放进来,然后每次再访问进来时候,把超时或者是不符合的时间戳给剔除。
    			然后根据它时间记录的个数来做判断。
    		
    		匿名用户:无法控制,因为用户可以换代理IP,所以没发做。
    			{
    				192.168.1.1:[1521223123.232, 1521223122.232, 1521223121.232],
    				192.168.1.2:[1521223123.232, 1521223122.232, 1521223121.232],
    				192.168.1.3:[1521223123.232, 1521223122.232, 1521223121.232],
    				192.168.1.4:[1521223123.232, 1521223122.232, 1521223121.232],
    				192.168.1.5:[1521223123.232, 1521223122.232, 1521223121.232],
    				192.168.1.6:[1521223123.232, 1521223122.232, 1521223121.232],
    				先剔除时间
    			}
    		
    		真要做匿名用户的访问频率的话,可以给匿名用户给随机的字符串,然后给每次访问的时候都带着,用它来记录时间,但是这样也不行,因为浏览器如果不带的话,每次都是第一次访问。凭我现在的能力,还没有办法能解决,想问您有什么解决的好办法呢
    		
    		登录用户:如果有很多账号,也无法限制
    			{
    				alex:[1521223123.232, 1521223122.232, 1521223121.232],
    				eric:[1521223123.232, 1521223122.232, 1521223121.232],
    			}
    		
    		参考源码:from rest_framework.throttling import SimpleRateThrottle
    		
    

      

    SimpleRateThrottle请求频率源码分析

    https://blog.csdn.net/u013210620/article/details/79898512 

      

    3.版本

    a. 基于url的get传参方式QueryParameterVersioning  

    如:/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/', TestView.as_view(),name='test'),
    ]
    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请求,响应内容')
    

      

    from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning
    # URLPathVersioning 是把版本放在url上;最常用的
    # QueryParameterVersioning  是把版本当做get的参数 ?version
    

      

    基于url的正则方式(URLPathVersioning  

    如:/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<version>[v1|v2]+)/test/', TestView.as_view(), name='test'),
    ]
    
    rom 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请求,响应内容')  

    全局使用

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

    更多的方式参考https://www.cnblogs.com/wupeiqi/articles/7805382.html

    4. 解析器(parser) 

    #解析器
    from rest_framework.parsers import JSONParser
    from rest_framework.parsers import FormParser
    from rest_framework.parsers import MultiPartParser
    from rest_framework.parsers import FileUploadParser
    
    # parser_classes = [JSONParser,FormParser,MultiPartParser]  #解析器,即按照content-type的不同来处理数据
    
    #仅处理请求头content-type为application/json的请求体为JSONParser
    #仅处理请求头content-type为application/x-www-form-urlencoded 的请求体为FormParser
    #仅处理请求头content-type为multipart/form-data的请求体为MultiPartParser  #form表单上传文件 

    同时多个Parser,单个使用的使用就写需要用的那个

    from django.conf.urls import url, include
    from web.views import TestView
    
    urlpatterns = [
        url(r'test/', TestView.as_view(), name='test'),
    ]
    
    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请求,响应内容') 

    全局使用 

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

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

    5. 序列化

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

    基于Model自动生成字段

    from rest_framework import serializers
    from app01.models import *
    
    
    class CouserSerializers(serializers.ModelSerializer):
    	'''
    	课程的序列化
    	'''
    	#自定义的字段
    
    	#source为表里面的所有字段
    	level = serializers.CharField(source='get_level_display') #自动的帮你添加()
    	course_type = serializers.CharField(source='get_course_type_display')
    
    	class Meta:
    		model = Course
    		fields = ["id",'name',"course_img","course_type","brief","level","period"]
    		# depth=2  用深度帮你进行跨表
    
    
    class CourseDetailViewSerializers(serializers.ModelSerializer):
    	'''
    	详细课程的序列化
    	'''
    	#一对一的反向查询,fk,choice都是用source,只能取一条或者是一个数据
    	name = serializers.CharField(source='course.name')
    	img = serializers.CharField(source='course.course_img')
    	content = serializers.CharField(source='course.brief')
    	id = serializers.CharField(source='course.id')
    
    	#多对多的,用SerializerMethodField(),可以获取多个
    
    	#推荐课程
    	recommend_courses = serializers.SerializerMethodField()
    	#老师
    	teachers= serializers.SerializerMethodField()
    	# 每个时间段的价格
    	price = serializers.SerializerMethodField()
    
    	# 课程大纲
    	course_detail = serializers.SerializerMethodField()
    
    	#课程章节
    	coursechapter = serializers.SerializerMethodField()
    	#
    	# #课时目录
    	# coursesection = serializers.SerializerMethodField()
    
    	# 推荐课程
    	def get_recommend_courses(self,obj):  #obj-->  CourseDetail.obj
    		# obj.recommendcourse.all()
    		return [{"id":item.id,"title":item.name}for item in obj.recommend_courses.all()]
    
    	def get_teachers(self,obj):  #obj-->  CourseDetail.obj
    		# obj.recommendcourse.all()
    		return [{"id":item.id,"name":item.name,"title":item.title}for item in obj.teachers.all()]
    	# 每个时间段的价格
    	def get_price(self,obj):
    		return [{"valid_period":item.get_valid_period_display(),"price":item.price}for item in obj.course.price_policy.all()]
    
    	def get_course_detail(self,obj):
    		return [{"title":item.title,"content":item.content}for item in obj.courseoutline_set.all()]
    
    	def get_coursechapter(self,obj):
    		return [{"chapter":item.chapter,"title":item.name,"summarys":item.summary}for item in obj.course.coursechapters.all()]
    
    	# def get_coursesection(self,obj):
    	# 	return [{"chapter":item.chapter,"name":item.name,"summary":item.summary}for item in obj.course.coursechapters.coursesections.all()]
    
    	class Meta:
    		model = CourseDetail
    
    		fields = ["id","name","img","hours","teachers","content",'why_study',"what_to_study_brief",
    		          "career_improvement","prerequisite","recommend_courses","price",'course_detail','coursechapter',]
    
    class TestView(APIView):
        def get(self, request, *args, **kwargs):
    
            # 序列化,将数据库查询字段序列化为字典
            data_list = models.UserInfo.objects.all()
            ser = CourseDetailViewSerializers(instance=data_list, many=True)
            # 或
            # obj = models.UserInfo.objects.all().first()
            # ser = CourseDetailViewSerializers(instance=obj, many=False)
            return Response(ser.data)
    
        def post(self, request, *args, **kwargs):
            # 验证,对请求发来的数据进行验证
            print(request.data)
            ser = CourseDetailViewSerializers(data=request.data)
            if ser.is_valid():
                print(ser.validated_data)
            ser.save() #直接保存到数据库,在这里会调用GoodSerializer的create方法。
    else: print(ser.errors) return Response('POST请求,响应内容')

      

    6. 分页

    a根据页码进行分页

    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
    

      

    b位置和个数进行分页

    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
    
    views.py
    

      

    7. 路由系统

    a. 自定义路由

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

    b. 半自动路由

    from django.conf.urls import url,include
    from django.contrib import admin
    from app01 import views
    
     url(r'^api/(?P<version>w+)/bookviewset/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name='bookviewset'),
        url(r'^api/bookviewset/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name='bookviewset'),
    
        # url(r'^bookviewset/(?P<pk>d+)$', views.BookViewSet.as_view({"get":"retrieve","post":"update"}), name='bookviewsetdetail'), 

    c. 全自动路由

    from django.conf.urls import url,include
    from rest_framework import routers
    from app01 import views
    router = routers.DefaultRouter()
    
    router.register("bookviewset",views.BookViewSet)
    
    url(r'',include(router.urls)),
    
        #自动的帮你生成4个url
        #^bookviewset/$ [name='book-list']
        #^bookviewset.(?P<format>[a-z0-9]+)/?$ [name='book-list']   .json?format=json
        #^bookviewset/(?P<pk>[^/.]+)/$ [name='book-detail']
        #^bookviewset/(?P<pk>[^/.]+).(?P<format>[a-z0-9]+)/?$ [name='book-detail']
    

    8. 视图

    根据继承的类的不同有不同的形式

                            class View(object):
    			
    			class APIView(View):
    			
    			class GenericAPIView(views.APIView):
    			
    			class GenericViewSet(ViewSetMixin, generics.GenericAPIView)
    			# ViewSetMixin 是对as_view里面的参数进行处理
    			
    			class ModelViewSet(mixins.CreateModelMixin,
                       mixins.RetrieveModelMixin,
                       mixins.UpdateModelMixin,
                       mixins.DestroyModelMixin,
                       mixins.ListModelMixin,
                       GenericViewSet):                    
    

    ViewSetMixin 

    url(r'^api/(?P<version>w+)/bookviewset/$', views.BookViewSet.as_view({"get":"list","post":"create"}),name='bookviewset')  

    没有继承ViewSetMixin 这个类的话get请求就是执行对应的get的方法。

    ModelViewSet把上面的增删改查都包含了,减少了我们自己写麻烦。

    from app01.forms import TokenAuth,SVIPPermisson
    
    #解析器
    from rest_framework.parsers import JSONParser
    from rest_framework.parsers import FormParser
    from rest_framework.parsers import MultiPartParser
    
    #版本
    from rest_framework.versioning import URLPathVersioning,QueryParameterVersioning
    class BookViewSet(viewsets.ModelViewSet):
    	authentication_classes=[TokenAuth,]        #认证组件
    	# permission_classes = [SVIPPermisson,]   #权限组件
    	# throttle_classes = []   #频率组件
    	# parser_classes = [JSONParser,FormParser,MultiPartParser]  #解析器,即按照content-type的不同来处理数据
    	queryset = Book.objects.all()             # 取的数据
    	print(queryset)
    	serializer_class = BookModelSerializers   #	序列化器
    	pagination_class = MyPageNumberPagination  #分页器
    

      

    10. 渲染器

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

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

    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/ 
    from rest_framework.renderers import AdminRenderer
     renderer_classes = [AdminRenderer, ] 

    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/ 
    from rest_framework.renderers import HTMLFormRenderer
    renderer_classes = [HTMLFormRenderer, ]
    

      

    等更多渲染器的形式点击查看  

      

      

    完整全面的内容点击  

      

     

      

      

      

     

      

      

      

     

    # URLPathVersioning 是把版本放在url上;最常用的
    # QueryParameterVersioning 是把版本当做get的参数 ?version
  • 相关阅读:
    Joomla 3.9.13 二次注入分析(CVE-2019-19846)
    Wordpress未授权查看私密内容漏洞 分析(CVE-2019-17671)
    Thinkphp 5.1.24 parseKey缺陷导致聚合注入 分析
    Thinkphp 5.1.7 parseData缺陷导致insert/update注入 分析
    Oracle笔记2
    Oracle笔记1
    k8s之helm入门
    k8s之自定义指标API部署prometheus
    k8s之资源指标API部署metrics-server
    k8s之调度器、预选策略及优选函数
  • 原文地址:https://www.cnblogs.com/zenghui-python/p/11731669.html
Copyright © 2020-2023  润新知