posts - 50,comments - 0,views - 22288

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

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

 

1.认证和授权

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
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

 

认证和权限

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
#!/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里面去配置全局信息。

1
2
3
4
5
6
7
8
9
10
REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": [
        "web.utils.TestAuthentication",
    ],
    "DEFAULT_PERMISSION_CLASSES": [
        "web.utils.TestPermission",
    ],
}
 
settings.py

 

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

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

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

1
2
3
4
5
6
7
8
from django.conf.urls import url, include
from web.views import TestView
 
urlpatterns = [
    url(r'^test/', TestView.as_view()),
]
 
urls.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
#!/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缓存)常用的  

1
2
3
4
5
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_RATES': {
        'test_scope': '10/m',
    },
}  

 

在源码中

1
2
3
4
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次

1
2
3
4
5
6
from django.conf.urls import url, include
from web.views import TestView
 
urlpatterns = [
    url(r'^test/', TestView.as_view()),
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/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

  

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
如何实现的访问频率控制?
 
       访问频率控制的原理:
           用户进来时候,把它的访问时间记录全部放进来,然后每次再访问进来时候,把超时或者是不符合的时间戳给剔除。
           然后根据它时间记录的个数来做判断。
        
       匿名用户:无法控制,因为用户可以换代理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 

1
2
3
4
5
REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',            # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    'VERSION_PARAM': 'version'          # URL中获取值的key
}
1
2
3
4
5
6
from django.conf.urls import url, include
from web.views import TestView
 
urlpatterns = [
    url(r'^test/', TestView.as_view(),name='test'),
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
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请求,响应内容')

  

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

  

基于url的正则方式(URLPathVersioning  

如:/v1/users/  

1
2
3
4
5
REST_FRAMEWORK = {
    'DEFAULT_VERSION': 'v1',            # 默认版本
    'ALLOWED_VERSIONS': ['v1', 'v2'],   # 允许的版本
    'VERSION_PARAM': 'version'          # URL中获取值的key
}
1
2
3
4
5
6
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'),
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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请求,响应内容')  

全局使用

1
2
3
4
5
6
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) 

1
2
3
4
5
6
7
8
9
10
11
#解析器
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,单个使用的使用就写需要用的那个

1
2
3
4
5
6
from django.conf.urls import url, include
from web.views import TestView
 
urlpatterns = [
    url(r'test/', TestView.as_view(), name='test'),
]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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请求,响应内容'

全局使用 

1
2
3
4
5
6
7
8
REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':[
        'rest_framework.parsers.JSONParser'
        'rest_framework.parsers.FormParser'
        'rest_framework.parsers.MultiPartParser'
    ]
 

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

5. 序列化

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

基于Model自动生成字段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
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',]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
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)<br>        ser.save()  #直接保存到数据库,在这里会调用GoodSerializer的create方法。<br>
        else:
            print(ser.errors)
 
        return Response('POST请求,响应内容')

  

6. 分页

a根据页码进行分页

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
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位置和个数进行分页

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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. 自定义路由

1
2
3
4
5
6
7
8
9
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. 半自动路由

1
2
3
4
5
6
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'),
1
# url(r'^bookviewset/(?P<pk>\d+)$', views.BookViewSet.as_view({"get":"retrieve","post":"update"}), name='bookviewsetdetail'), 

c. 全自动路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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. 视图

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
            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 

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

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

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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/ 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
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/ 
1
from rest_framework.renderers import AdminRenderer
1
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/ 
1
2
from rest_framework.renderers import HTMLFormRenderer
renderer_classes = [HTMLFormRenderer, ]

  

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

  

  

完整全面的内容点击  

  

 

  

 

  

  

 

  

  

  

 

# URLPathVersioning 是把版本放在url上;最常用的
# QueryParameterVersioning 是把版本当做get的参数 ?version
posted on   小辉python  阅读(370)  评论(0编辑  收藏  举报
编辑推荐:
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· Linux系列:如何调试 malloc 的底层源码
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
阅读排行:
· 对象命名为何需要避免'-er'和'-or'后缀
· JDK 24 发布,新特性解读!
· Java24你发任你发,我用Java8
· .NET Core奇技淫巧之WinForm使用Python.NET并打包
· C# 中比较实用的关键字,基础高频面试题!
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

点击右上角即可分享
微信分享提示