Django之Rest_Framework http://www.cnblogs.com/wupeiqi/articles/7805382.html

1.认证功能
1.1 创建两张表

from django.db import models

class UserInfo(models.Model):
    """
    用户表
    """
    user_type_id = (
        (1,'普通用户'),
        (2,'VIP用户'),
        (3,'SVIP用户'),
    )
    user_type = models.IntegerField(choices=user_type_id,max_length=32)
    username = models.CharField(verbose_name='用户名',max_length=32,unique=True)
    password = models.CharField(verbose_name='密码',max_length=64)


class TokenInfo(models.Model):
    """
    token表
    """	
    user = models.OneToOneField(to='UserInfo') # 和用户表做一对一关联
    token = models.CharField(verbose_name='Token',max_length=128)    

 

 

1.2 编写用户登录认证,并保存token到数据库中

 1 import hashlib
 2 import time
 3 from django.shortcuts import render
 4 from django.http import JsonResponse
 5 from rest_framework.views import APIView
 6 from api import models
 7 
 8 def md5(user):
 9     """
10     通过MD5加密把时间戳变成token
11     :param user: 
12     :return: 
13     """
14     ctime = str(time.time())
15     md5_obj = hashlib.md5(bytes(user,encoding='utf-8'))
16     md5_obj.update(bytes(ctime,encoding='utf-8'))
17     return md5_obj.hexdigest()
18 
19 class AuthView(APIView):
20     """
21     API
22     """
23     def post(self,request,*args,**kwargs):
24         """
25         用户登录
26         :param request: 
27         :param args: 
28         :param kwargs: 
29         :return: 
30         """
31         ret = {'code':1000,'msg':None}
32         try:
33             # 获取post提交过来的用户名和密码
34             user = request._request.POST.get('username')
35             pwd = request._request.POST.get('password')
36 
37             # 从数据库中获取用户名密码的对象
38             user_obj = models.UserInfo.objects.filter(username=user,password=pwd).first()
39 
40             # 判断用户名和密码
41             if not user_obj:
42                 ret['code'] = 1001
43                 ret['msg'] = '用户名密码错误'
44 
45             # 为登录用户创建token
46             token = md5(user)
47                 models.TokenInfo.objects.update_or_create(user=user_obj,defaults={'token':token})
48 
49             ret['token'] = token
50         except Exception as e:
51             ret['code'] = 1002
52             ret['msg'] = '认证失败'
53 
54         return JsonResponse(ret)    
View Code

1.3 完善登录认证功能

djangorestframework\api\utils\auth.py 下定义认证功能

 1 from api import models
 2 from rest_framework import exceptions
 3 from rest_framework.authentication import BaseAuthentication
 4 class Authtication(BaseAuthentication):
 5     """
 6     定义认证规则
 7     """
 8     def authenticate(self, request):
 9         token = request._request.GET.get('token')
10         token_obj = models.TokenInfo.objects.filter(token=token).first()
11         if not token:
12             raise exceptions.AuthenticationFailed('用户认证失败')
13         return (token_obj.user, token)
14 
15     def authenticate_header(self,request):
16         pass
View Code

认证规则写完以后,添加url写其他功能


1.4 编写测试代码(模拟获取订单信息,按照restful规定写)

 

 1 class OrderView(APIView):
 2     """
 3     模拟订单的增删改查
 4     """
 5 
 6     def get(self, request):
 7         """
 8         get请求为查询订单
 9         :param request: 
10         :return: 
11         """
12         ret = {'code': 1000, 'msg': None, 'data': None}
13         try:
14             ret['data'] = ORDER_DICT
15         except Exception as e:
16             pass
17         return JsonResponse(ret)    
View Code

 

1.5 设置全局认证方式

1 REST_FRAMEWORK = {
2     'DEFAULT_AUTHENTICATION_CLASSES':['api.utils.auth.Authtication'],   # 用户认证
3     'UNAUTHENTICATED_USER':None,  # 匿名用户
4     'UNAUTHENTICATED_TOKEN':None, # 匿名用户
5 }
api认证全局配置

 

1.6 url访问

127.0.0.1:8000/api/v1/auth/ # 发送post请求,生成当前用户的token
127.0.0.1:8000/api/v1/order/?token=bf7b137c8d33a9b90a2b64ee6fda0f49 #携带token发送get请求,先走认证功能,如果不携带token走到认证功能是则返回认证失败

 

2.权限
2.1 权限代码

 1 from rest_framework.permissions import BasePermission
 2 
 3 class MainPermission(BasePermission):
 4     """
 5     权限
 6     """
 7     def has_permission(self, request, view):
 8 
 9         # 用户user_type等于2时,有权限,其他则没有
10         if request.user.user_type == 2:
11             return True
12         return False
View Code

 

2.2 全局使用和局部使用

1 # settings配置文件中
2 REST_FRAMEWORK = {
3     'DEFAULT_PERMISSION_CLASSES':['api.utils.permission.MainPermission'],
4 }
api认证全局配置之权限

 如果是局部使用的话则和认证的局部使用是一样的

permission_classes = [MainPermission,]

2.3 测试代码

 1 class OrderView(APIView):    
 2     """
 3     模拟订单的增删改查
 4     """
 5     def get(self, request):
 6         """
 7         get请求为查询订单
 8         :param request: 
 9         :return: 
10         """
11         ret = {'code': 1000, 'msg': None, 'data': None}
12         try:
13             ret['data'] = ORDER_DICT
14         except Exception as e:
15             pass
16         return JsonResponse(ret)
View Code

 

2.4 url访问

127.0.0.1:8000/api/v1/order/?token=bf7b137c8d33a9b90a2b64ee6fda0f49 # get请求,如果token是user_type == 2的用户的,则有权限,其他则没有

 

3.节流(访问频率控制)
3.1 节流之自定义

3.1.1 访问控制代码

 1 from rest_framework.throttling import BaseThrottle
 2 import time
 3 
 4 VISIT_RECORD = {} # 真实环境中要放到redis中
 5 
 6 class VisitThrottle(BaseThrottle):
 7     """
 8     访问频率控制
 9     """
10     def __init__(self):
11         self.history = None
12 
13     def allow_request(self, request, view):
14 
15         # 获取client的ip地址
16         remote_addr = request.META.get('REMOTE_ADDR')
17         ctime = time.time()
18 
19         # 判断获取到的ip地址是否在VISIT_RECORD字典中
20         if remote_addr not in VISIT_RECORD:
21 
22             # 没有则创建,值为列表
23             VISIT_RECORD[remote_addr] = [ctime,]
24             return True
25 
26         history = VISIT_RECORD.get(remote_addr)
27         self.history = history
28 
29         # 如果列表中有值,且最后面的值大于当前时间-60,则将其删除
30         while history and history[-1] < ctime - 60:
31             history.pop()
32             # 如果列表总长度小于3,则把新访问的时间放到列表的第一位
33         if len(history) < 3:
34             history.insert(0,ctime)
35             return True
36 
37     def wait(self):
38         """
39         等待多时秒后才能访问
40         :return: 
41         """
42         ctime = time.time()
43         return 60-(ctime-self.history[-1])
View Code

3.1.2 全局应用(局部应用和认证和权限一样)

1 REST_FRAMEWORK = {
2     'DEFAULT_THROTTLE_CLASSES':['api.utils.throttle.VisitThrottle'], 
3 }
View Code

3.1.3 测试代码

 1 class OrderView(APIView):
 2     """
 3     模拟订单的增删改查
 4     """
 5 
 6     def get(self, request):
 7         """
 8         get请求为查询订单
 9         :param request: 
10         :return: 
11         """
12         ret = {'code': 1000, 'msg': None, 'data': None}
13         try:
14             ret['data'] = ORDER_DICT
15         except Exception as e:
16             pass
17         return JsonResponse(ret)    
View Code

3.1.4 url访问

127.0.0.1:8000/api/v1/order/?token=bf7b137c8d33a9b90a2b64ee6fda0f49 # 可登录和有权限的用户

访问超过三次后,返回值为:
{
    "detail": "请求超过了限速。 Expected available in 48 seconds."
}

 

3.2.节流之rest_framework内置类
3.2.1 基于时间的访问频率
a.代码块

1 class VisitThrottle(SimpleRateThrottle):
2     scope = 'Luffy' # 设置配置文件中所需要的key
3     
4     def get_cache_key(self, request, view): # 调用内置方法
5         return self.get_ident(request)
View Code

b.配置文件

1 REST_FRAMEWORK = {
2     'DEFAULT_THROTTLE_RATES':{
3         'Luffy':'3/m',  # 每分钟三次
4     }
5 }
View Code

3.2.2 基于username的访问频率
a.基于用户的访问控制

1 class UserThrottle(SimpleRateThrottle):
2     scope = 'LuffyUser'
3 
4     def get_cache_key(self, request, view):
5         return request.user.username
View Code

 

b.配置文件

1 REST_FRAMEWORK = {
2     'DEFAULT_THROTTLE_RATES':{
3         'LuffyUser':'5/m', # 每分钟5次
4     }
5 }
View Code

PS:如果是基于时间访问和基于用户访问同时存在的话,那在配置文件中只设置为基于用户的访问控制就可以,

1 REST_FRAMEWORK = {
2     'DEFAULT_THROTTLE_CLASSES':['api.utils.throttle.UserThrottle'], 
3 }
View Code

在自定义的认证类中设置基于频率的访问控制

class AuthView(APIView):
    """
    API
    """
    # 不需要被全局认证的则设置成空列表
    authentication_classes = []
    permission_classes = []

    throttle_classes = [VisitThrottle,]

    ......

 

 

4.版本
4.1 自定义获取版本

访问的 url= 127.0.0.1:8000/api/users/?version=v2&token=bf7b137c8d33a9b90a2b64ee6fda0f49    # get请求
 1 class ParamVersion:
 2     """
 3     获取版本号
 4     """
 5     def determine_version(self,request,*args,**kwargs):
 6 
 7         # 调用rest_framework内置方法query_params
 8         version = request.query_params.get('version')
 9         return version
10 
11 
12 class UserView(APIView):
13     """
14     测试获取版本号
15     """
16     versioning_class = ParamVersion
17 
18     def get(self,request,*args,**kwargs):
19         print(request.version)
20         return HttpResponse('....')
View Code

 

4.2 使用内置方法获取版本

访问的 url= 127.0.0.1:8000/api/users/?version=v2&token=bf7b137c8d33a9b90a2b64ee6fda0f49   # get请求
 1 from rest_framework.versioning import QueryParameterVersioning
 2 class UserView(APIView):
 3     """
 4     测试获取版本号
 5     """
 6     # 通过rest_framework内置方法可以直接获取到版本号
 7     versioning_class = QueryParameterVersioning
 8 
 9     def get(self,request,*args,**kwargs):
10         print(request.version)
11         return HttpResponse('....')
View Code

4.2.1 在配置文件中设置为可以获取默认版本

REST_FRAMEWORK = {
    'DEFAULT_VERSION':'v1', # 默认不传参数所获取的版本
    'ALLOWED_VERSIONS':['v1','v2','v3'], # 允许使用的版本
    'VERSION_PARAM':'version',   # get方式默认的传参方式
}
url访问 127.0.0.1:8000/api/users/?token=bf7b137c8d33a9b90a2b64ee6fda0f49 # 不传参数时,默认的就是获取到的版本就是v1

4.3 通过定义url获取版本号

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/users/$', views.UserView.as_view()), # (?P<version>[v1|v2]+)定义版本的正则表达式
]

REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':'rest_framework.versioning.URLPathVersioning', # 获取到URLPathVersioning的全路径
}    

4.3.1  测试代码

1 class UserView(APIView):
2     """
3     测试获取版本号
4     """
5     def get(self,request,*args,**kwargs):
6         print(request.version)
7         return HttpResponse('....')
View Code
url访问 127.0.0.1:8000/api/v2/users/?token=bf7b137c8d33a9b90a2b64ee6fda0f49

 

5.解析器(对于解析器来说,主要是通过request.data来取值的)
5.1 配置文件settings中的配置

1 REST_FRAMEWORK = {
2 
3     # JSONParser只支持json格式的数据,FormParser支持字符串格式的数据
4     'DEFAULT_PARSER_CLASSES':['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser'],
5 }
View Code

5.2 测试代码

 1 class ParserView(APIView):
 2 
 3     def post(self,request,*args,**kwargs):
 4     """
 5     1.获取请求头和请求体
 6     2.根据用户的请求头和parser_classes = [JSONParser,FormParser]所    支持的请求头比较,符合那个请求用那个方法
 7     3.通过request.data获取最终数据
 8     """
 9 
10     print(request.data)
11     print(request.data['name'])
12     return HttpResponse(self)
View Code

 

5.3 url配置

1 urlpatterns = [
2     url(r'^(?P<version>[v1|v2]+)/parser/$', views.ParserView.as_view()),
3 ]
View Code
url访问 127.0.0.1:8000/api/v2/parser/?token=bf7b137c8d33a9b90a2b64ee6fda0f49

 

 

6.序列化
序列化分为两大功能:
a.将queryset数据类型序列化后返回给用户
b.对数据进行验证

6.1 单一表的操作

 1 import json
 2 from rest_framework import serializers
 3 
 4 class RolesSerializer(serializers.Serializer):
 5     """
 6     自定义类,继承rest_framework内置序列化模块Serializer
 7     """
 8     # 获取数据库中的表字段,且字段名是什么 就写什么
 9     title = serializers.CharField()
10 
11 class RolesView(APIView):
12     def get(self,request,*args,**kwargs):
13 
14         # 方式一,
15         # 1.把queryset对象用list进行转换
16         # 2.通过json序列化把转换后的列表序列化
17         roles = list(models.Role.objects.all().values('id','title'))
18         ret = json.dumps(roles,ensure_ascii=False)
19 
20         # 方式二
21         # 1.获取queryset对象
22         roles = models.Role.objects.all()
23         # 2.实例化自定义的类,instance=roles表示要被序列化的对象 ,many=True表示序列化多个对象
24         ser = RolesSerializer(instance=roles,many=True)
25         # 3.通过ser.data获取到所有数据,再通过json序列化
26         ret = json.dumps(ser.data,ensure_ascii=False)
27 
28         # 方式三
29         # 1.获取单个对象
30         role = models.Role.objects.all().first()
31         # 2.在实例化自定义类的时候many就必须等于False
32         ser = RolesSerializer(instance=role,many=False)
33         ret = json.dumps(ser.data,ensure_ascii=False)
34 
35         return HttpResponse(ret)
View Code

 

6.2 多功能表的操作

url配置
urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/userinfo/$', views.UserInfoView.as_view()),
]

 

6.2.1 基于Serializer实现数据库字段的序列化

 1 class UserInfoSerializer(serializers.Serializer):
 2 
 3     # 获取有关choices类型中数字所对应的中文值
 4     usertype = serializers.CharField(source='get_user_type_display')
 5     username = serializers.CharField()
 6     password = serializers.CharField()
 7 
 8     # 获取ForeignKey关联数据
 9     gp = serializers.CharField(source='group.title')
10 
11     # 获取ManyToManyField关联数据,需要自定义函数
12     role = serializers.SerializerMethodField()
13 
14     def get_role(self,row):
15         ret = []
16         roles_obj = row.roles.all()
17         for item in roles_obj:
18         ret.append(item.title)
19         return ret
View Code

6.2.2 基于ModelSerializer实现数据库字段的序列化

 1 class UserInfoSerializer(serializers.ModelSerializer):
 2     # 自定义获取有关choice类型的数据中文值
 3     usertype = serializers.CharField(source='get_user_type_display')
 4 
 5     # 自定义获取ManyToManyField关联数据
 6     role = serializers.SerializerMethodField()
 7 
 8     class Meta:
 9         model = models.UserInfo
10         # 将需要展示的字段放到列表里面
11         fields = ['id','username','password','usertype','role']
12 
13         # 如果需要全部字段,则:
14         # fields = "__all__"
15 
16     def get_role(self,row):
17         ret = []
18         roles_obj = row.roles.all()
19         for item in roles_obj:
20             ret.append(item.title)
21         return ret
View Code

6.2.3 基于ModelSerializer实现数据库字段的序列化自动连表操作

1 class UserInfoSerializer(serializers.ModelSerializer):    
2     class Meta:
3         model = models.UserInfo
4         # 获取普通字段
5         fields = ['id','user_type','username','password','group','roles']
6 
7         depth = 1 # 取数据库中深层数据 建议层数范围是0-10,0为第一层
View Code

返回结果

 1 {
 2     "id": 1,
 3     "user_type": 1,
 4     "username": "eric",
 5     "password": "123123",
 6     "group": {
 7         "id": 1,
 8         "title": "A"
 9     },
10     "roles": [
11         {
12             "id": 1,
13             "title": "老师"
14         },
15         {
16             "id": 2,
17             "title": "校长"
18         },
19         {
20             "id": 3,
21             "title": "班主任"
22         }
23     ]
24 },
View Code

测试代码

1 class UserInfoView(APIView):
2     def get(self,reqeust,*args,**kwargs):
3         users = models.UserInfo.objects.all()
4         ser = UserInfoSerializer(instance=users,many=True)
5         ret = json.dumps(ser.data,ensure_ascii=False)
6         return HttpResponse(ret)
View Code

 

6.3 序列化之在返回的数据中生成url
url配置

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/userurl/(?P<pk1>\d+)/$', views.UserUrlView.as_view(),name='users'),
    url(r'^(?P<version>[v1|v2]+)/group/(?P<pk2>\d+)/$', views.GroupUrlView.as_view(),name='gp'),
]
 1 class UserInfoSerializer(serializers.ModelSerializer):
 2 
 3     """
 4     通过ModelSerializer生产返回数据中的url
 5     """
 6 
 7     # view_name='users' 中的users则是url中的name,pk1则是(?P<pk1>\d+)中的pk1
 8     username = serializers.HyperlinkedIdentityField(view_name='user',lookup_url_kwarg='pk1') 
 9 
10     # 如果有数据库中有ForeignKey就需要在实例化    HyperlinkedIdentityField的时候加上lookup_field='group_id'
11     group = serializers.HyperlinkedIdentityField(view_name='gp', lookup_field='group_id',lookup_url_kwarg='pk2')
12     class Meta:
13         model = models.UserInfo
14         # 获取普通字段
15         fields = ['id','user_type','username','password','group','roles']
16         depth = 1
View Code
 1 class UserInfoView(APIView):
 2     """
 3     返回序列化后的数据
 4     """
 5     def get(self,request,*args,**kwargs):
 6         users = models.UserInfo.objects.all()
 7         ser = UserInfoSerializer(instance=users,many=True,context={'request': request})
 8         ret = json.dumps(ser.data,ensure_ascii=False)
 9         return HttpResponse(ret)
10 
11 
12 class GroupSerializer(serializers.ModelSerializer):
13     """
14     通过生成后的url获取用户组的所需数据
15     """
16     class Meta:
17         model = models.UserGroup
18         fields = '__all__'
19 
20 class UserSerializer(serializers.ModelSerializer):
21     """
22     通过生成后的url获取用户的所需数据
23     """
24     class Meta:
25         model = models.UserInfo
26         fields = ['username']
27 
28 
29 class UserUrlView(APIView):
30     """
31     生成用户名对应的url
32     """
33     def get(self,request,*args,**kwargs):
34         pk = kwargs.get('pk')
35         user_obj = models.UserInfo.objects.filter(pk=pk).first()
36         ser = UserSerializer(instance=user_obj,many=False)
37 
38         ret = json.dumps(ser.data,ensure_ascii=False)
39 
40         return HttpResponse(ret)
41 
42 
43 class GroupUrlView(APIView):
44     """
45     生成用户组对应的url
46     """
47     def get(self,request,*args,**kwargs):
48         pk = kwargs.get('pk')
49         group_obj = models.UserGroup.objects.filter(pk=pk).first()
50         ser = GroupSerializer(instance=group_obj,many=False,)
51 
52         ret = json.dumps(ser.data,ensure_ascii=False)
53         return HttpResponse(ret)    
View Code

返回结果

 1 {
 2     "id": 1,
 3     "user_type": 1,
 4     "username": "http://127.0.0.1:8000/api/v2/userurl/1/", # 通过url可以获取到对应的数据
 5     "password": "123123",
 6     "group": "http://127.0.0.1:8000/api/v2/group/1/",
 7     "roles": [
 8         {
 9             "id": 1,
10             "title": "老师"
11         },
12         {
13             "id": 2,
14             "title": "校长"
15         },
16         {
17             "id": 3,
18             "title": "班主任"
19         }
20      ]
21 },
View Code

 

7.分页(三个方法)
7.1 分多少页,每页显示多少数据 (PageNumberPagination类)
7.1.1 定义一个获取数据库数据的serializer

1 from rest_framework import serializers
2 from api import models
3 
4 class PagerSerializer(serializers.ModelSerializer):
5     class Meta:
6         model = models.Role
7         fields = '__all__'
View Code

 

7.1.2 使用rest_framework内置方法
定义url

1 urlpatterns = [
2     url(r'^admin/', admin.site.urls),
3     url(r'^(?P<version>[v1|v2]+)/pager/', views.PagerView.as_view()),
4 ]
View Code

 

展示数据视图

 1 from api.utils.serializsers.Pager import PagerSerializer
 2 from rest_framework.response import Response
 3 from rest_framework.pagination import PageNumberPagination
 4 
 5 class PagerView(APIView):
 6     def get(self,request,*args,**kwargs):
 7 
 8         # 获取数据库所有数据
 9         roles = models.Role.objects.all()
10 
11         # 实例化PageNumberPagination
12         page = PageNumberPagination()
13 
14         # 通过对象page调用PageNumberPagination内置方法paginate_queryset,参数为queryset=roles 为queryset对象
15         roles_data = page.paginate_queryset(queryset=roles,request=request,view=self)
16         # 将数据库的数据序列化
17         ser = PagerSerializer(instance=roles_data, many=True)
18 
19         # 调用rest_framework的Response返回序列化后的数据
20         return Response(ser.data)
View Code

配置文件中:

1 REST_FRAMEWORK = {
2     'PAGE_SIZE':3, # 全局配置每页显示的条数
3 }
View Code


7.1.3 自定义方法

 1 from api.utils.serializsers.Pager import PagerSerializer
 2 from rest_framework.pagination import PageNumberPagination
 3 
 4 class MyPageNumberPagination(PageNumberPagination):
 5 
 6     # 设置每页显示几条数据
 7     page_size = 2
 8 
 9     # get传参的方式获取第几页数据的关键字
10     page_query_param = 'page'
11 
12     # get传参的方式定义每页显示多少条数据的关键字
13     page_size_query_param = 'size'
14 
15     # 每页最大显示数据条数
16     max_page_size = 4
自定义类MyPageNumberPagination
1 class PagerView(APIView):
2     def get(self,request,*args,**kwargs):
3         roles = models.Role.objects.all()
4         page = MyPageNumberPagination()
5         roles_data = page.paginate_queryset(queryset=roles,request=request,view=self)
6         ser = PagerSerializer(instance=roles_data, many=True)
7 
8         # 通过get_paginated_response可以获取到上一页下一页等按钮
9         return page.get_paginated_response(ser.data)
展示数据视图
 1 {
 2     "count": 10, # 数据库数据总条数
 3     "next": "http://127.0.0.1:8000/api/v2/pager/?    page=3&token=006473eea82c8544d6199a095c0bffe4", # 表示下一页
 4     "previous": "http://127.0.0.1:8000/api/v2/pager/?        token=006473eea82c8544d6199a095c0bffe4",    # 表示上一页
 5     "results": [
 6         {
 7             "id": 3,
 8             "title": "班主任"
 9         },
10         {
11             "id": 4,
12             "title": "警察"
13         }
14     ]
15 }
结果显示

 

7.2 指定索引位置,向后查看多少条数数据(LimitOffsetPagination)
7.2.1 继续使用定义好的serializer

djangorestframework\api\utils\serializsers\Pager.py
1 from rest_framework import serializers
2 from api import models
3 
4 class PagerSerializer(serializers.ModelSerializer):
5     class Meta:
6         model = models.Role
7         fields = '__all__'
View Code

7.2.2 使用内置方法

 1 from api.utils.serializsers.Pager import PagerSerializer
 2 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination
 3 class PagerView(APIView):
 4     def get(self,request,*args,**kwargs):
 5         roles = models.Role.objects.all()
 6 
 7         # 实例化LimitOffsetPagination
 8         page = LimitOffsetPagination()
 9         roles_data = page.paginate_queryset(queryset=roles,request=request,view=self)
10         ser = PagerSerializer(instance=roles_data, many=True)
11 return page.get_paginated_response(ser.data)
View Code

7.2.3 自定义方法

 

 1 class MyLimitOffsetPagination(LimitOffsetPagination):
 2 
 3     # 设置每页显示几条数据
 4     default_limit = 2
 5 
 6     # get传参的方式获取索引位置的关键字
 7     limit_query_param = 'limit'
 8 
 9     # get传参的方式定义每页向后显示多少条数据的关键字
10     offset_query_param = 'offset'
11 
12     # 每页最大显示数据条数
13     max_limit = 5
14 
15 
16 class PagerView(APIView):
17     def get(self,request,*args,**kwargs):
18         roles = models.Role.objects.all()
19 
20         # 实例化自定义的类
21         page = MyLimitOffsetPagination()
22         roles_data = page.paginate_queryset(queryset=roles,request=request,view=self)
23         ser = PagerSerializer(instance=roles_data, many=True)
24         # return Response(ser.data)
25 
26         # 使用page.get_paginated_response可以在页面展示的时候显示上一页和下一页
27         return page.get_paginated_response(ser.data)
View Code

 

7.3 加密页码 CursorPagination
7.3.1 继续使用定义好的serializer 

1 djangorestframework\api\utils\serializsers\Pager.py
2 from rest_framework import serializers
3 from api import models
4 
5 class PagerSerializer(serializers.ModelSerializer):
6     class Meta:
7         model = models.Role
8         fields = '__all__'
View Code

 

7.3.2 自定义方法

 1 from api.utils.serializsers.Pager import PagerSerializer
 2 from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
 3 
 4 class MyCursorPagination(CursorPagination):
 5 
 6     # get传参的方式获取第几页数据的关键字,但是不能那么传,会报错
 7     cursor_query_param = 'cursor'
 8 
 9     # 设置每页显示几条数据
10     page_size = 2
11 
12     # 数据显示的排序方式
13     ordering = 'id'
14 
15 class PagerView(APIView):
16     def get(self,request,*args,**kwargs):
17         roles = models.Role.objects.all()
18         page = MyCursorPagination()
19         roles_data = page.paginate_queryset(queryset=roles,request=request,view=self)
20         ser = PagerSerializer(instance=roles_data, many=True)
21         return page.get_paginated_response(ser.data)
View Code

 

8.视图
url设置

urlpatterns = [
  # 'get': 'retrieve':表示get请求,'post':'create':表示post请求,'put':'update':表示批量修改,'patch':'partial_update':表示局部修改,'delete':'destroy':表示删除操作
  url(r'^(?P<version>[v1|v2]+)/view1/(?P<pk>\d+)/$', views.ViewView.as_view({'get': 'retrieve','post':'create','put':'update','patch':'partial_update','delete':'destroy'})),
]
from rest_framework.viewsets import ModelViewSet
from api.utils.serializsers.Pager import PagerSerializer

class ViewView(ModelViewSet):

    # 获取要展示的数据的queryset对象
    queryset = models.Role.objects.all()

    # 获取被序列化后的要展示的信息
    serializer_class = PagerSerializer

    # 调用自定义的页码类,应该可以不用这个
    pagination_class =MyCursorPagination

在自定义的视图中,继承ModelViewSet,但同时ModelViewSet又分别继承了六个类

class ModelViewSet(mixins.CreateModelMixin, # 创建数据,相当于post请求
        mixins.RetrieveModelMixin,    # 获取单一数据,相当于get
        mixins.UpdateModelMixin,    # 更新数据,相当于put和patch
        mixins.DestroyModelMixin,    # 删除数据,相当于delete
        mixins.ListModelMixin,    # 获取多个数据,相当于get
        GenericViewSet):    # 通过继承GenericViewSet 可以获取到一些需要被展示的数据

9.路由
在URL中自动生成路由

from rest_framework import routers

router = routers.DefaultRouter()
router.register(r'abc',views.ViewView)

urlpatterns = [
    url(r'^(?P<version>[v1|v2]+)/', include(router.urls)), 
]
结果:

 

^api/ ^(?P<version>[v1|v2]+)/ ^abc/$ [name='role-list']
^api/ ^(?P<version>[v1|v2]+)/ ^abc\.(?P<format>[a-z0-9]+)/?$ [name='role-list']
^api/ ^(?P<version>[v1|v2]+)/ ^abc/(?P<pk>[^/.]+)/$ [name='role-detail']
^api/ ^(?P<version>[v1|v2]+)/ ^abc/(?P<pk>[^/.]+)\.(?P<format>[a-z0-9]+)/?$ [name='role-detail']

 

自动生成了四个url,这四个url提供增删改查功能

10.渲染
配置文件中配置:

# JSONRenderer只显示json数据,BrowsableAPIRenderer通过浏览器渲染后的数据
REST_FRAMEWORK = {
  'DEFAULT_RENDERER_CLASSES':['rest_framework.renderers.JSONRenderer','rest_framework.renderers.BrowsableAPIRenderer'], }

访问之前的url就能看出效果

posted on 2019-03-01 15:36  花豆豆  阅读(282)  评论(0编辑  收藏  举报