Django rest framework框架

一、十个方面

  权限  认证  访问频率限制 序列化 路由 视图 分页  解释器 渲染器 版本

二、Django REST framework框架介绍

  用于构建Web API,官方网站:https://www.django-rest-framework.org/

三、安装

  pip install djangorestframework

  pip install markdown #支持可浏览的API

  pip install django-filter # 过滤支持

四、设置setting.py文件  

#将项目添加到APP中
INSTALLED_APPS = [ ... 'rest_framework', ]
#添加中间件
REST_FRAMEWORK = {
    # Use Django's standard `django.contrib.auth` permissions,
    # or allow read-only access for unauthenticated users.
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.DjangoModelPermissionsOrAnonReadOnly'
    ]
}

五、用户登录API+验证

  1.创建用户表和用户登录验证的token

#models.py文件
class UserInfo(models.Model):
    user_type_choices=(
        (1,'普通用户'),
        (2, 'VIP'),
        (3, 'SVIP'),
    )
    id = models.AutoField(primary_key=True)
    user_type = models.IntegerField(choices=user_type_choices,verbose_name='用户等级')
    username = models.CharField(max_length=32,unique=True,verbose_name='用户名')
    password = models.CharField(max_length=64,verbose_name='用户密码')

class UserToken(models.Model):
    user = models.OneToOneField(to='UserInfo')
    token = models.CharField(max_length=64,verbose_name='用户的token')

  2.创建用户Token的md5算法  

#当前算法使用的hashlib的md5算法加上时间
import hashlib
import time
def md5(user):
    ctime = str(time.time())
    m = hashlib.md5(bytes(user,encoding='utf-8'))
    m.update(bytes(ctime,encoding='utf-8'))
    return m.hexdigets()

  3.根据用户名创建Token

from rest_framework.views import APIView
class AuthView(APIView):
    def post(self, request, *args, **kwargs):
        ret = {'code': 1000, 'msg': None}
        try:
            # 获取用户名
            user = request._request.POST.get('username')
            # 获取密码
            pwd = request._request.POST.get('password')
            # 核对数据的正确性
            obj = models.UserInfo.object.filter(username=user, password=pwd).first()
            if not obj:
                ret['code'] = 1001
                ret['msg'] = '用户名或密码错误'
            # 为登录用户创造token
            token = md5(user)
            # 存在就更新,不存在就创新
            models.UserToken.object.update_or_create(user=obj, defaults={'token': token})
            ret['token'] = token
        except Exception as e:
            ret['code'] = 1002
            ret['msg'] = '请求异常'
        return JsonResponse(ret)

   4.验证用户传递的Token是否正确,来验证登录用户是否正确

class Authtication(BasicAuthentication):
    def authenticate(self, request):
        token = request._request.Get.get('token')
        token_obj = models.UserToken.object.filter(token=token).first()
        if not token_obj:
            raise exceptions.AuthenticationFailed('用户验证失败')
        return (token_obj.user,token_obj)
    
    def authenticate_header(self, request):
        pass

  5.修改settings.py配置文件,加装全局变量配置

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES":['函数所在路径.函数名,如:api.utils.auth.Authtication']
}

  6.在其他视图函数中引用配置文件,完成只有登录用户才可以访问的控制

  authentication_classess= []

六、匿名用户登录

  1.修改settings.py配置文件,加装全局变量配置

REST_FRAMEWORK = {
    "DEFAULT_AUTHENTICATION_CLASSES": ['函数所在路径.函数名,如:api.utils.auth.Authtication'],
    "UNAUTHENTICATED_USER": None,
    "UNAUTHENTICATED_TOKEN": None
}

  2.创建匿名用户的验证函数

class FirstAuthtication(BasicAuthentication):
    def authenticate(self, request):
        pass
    
    def authenticate_header(self, request):
        pass

七、按权限限定用户访问的页面

  1.创建限制用户权限的函数

from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
   message = "只用3级用户才可以访问"
def has_permission(self, request, view): #只有3级用户才可以访问 if request.user.user_type !=3: return False else: return True

  2.视图函数使用验证方法(推举使用该方法,而不是全局配置)

  permission_classess = [MyPermission,]

八、控制访问频率次数

  1.创建访问频率次数的方法函数

import time
from rest_framework.throttling import BaseThrottle
VISIT_RECORD={}
class VisitThrottle(BaseThrottle):
    #60秒只能访问3次
    def __init__(self):
        self.history = None

    def allow_request(self, request, view):
        #获取用户的IP,根据IP进行控制
        ip = request.META.get("REMOTE_ADDR")
        ctime = time.time()
        if ip not in VISIT_RECORD:
            VISIT_RECORD[ip]=[ctime,]
            return True
        history = VISIT_RECORD.get(ip)
        self.history = history
        while history and history[-1] < ctime - 60:
            history.pop()
        if len(history) < 3:
            history.insert(0,ctime)
            return True

    def wait(self):
        '''
        需要等待多长时间再次访问
        :return:
        '''
        ctime = time.time()
        return  60 -(ctime-self.history[-1])

     2.使用框架内部的控制策略

#修改配置文件信息,settings.py
REST_FRAMEWORK = {
    "DEFAULT_THROTTLE_RATES":{
        "IP":'3/m',
        "UserName":'10/m'
    }
}
#设置控制策略函数
from rest_framework.throttling import SimpleRateThrottle
class VisitThrottle(SimpleRateThrottle):
    #根据IP的访问控制
    scope = "IP"
    def get_cache_key(self, request, view):
        return self.get_ident(request)

class UserThrottle(SimpleRateThrottle):
    #根据用户名的访问控制
    scope = "UserName"
    def get_cache_key(self, request, view):
        return request.user.username

九、版本控制策略

#修改配置文件信息
REST_FRAMEWORK = {
    #默认版本号
    "DEFAULT_VERSION":'v1',
    #允许的版本号
    "ALLOWED_VERSIONS":['v1','v2'],
    #版本的Key的值
    "VERSION_PARAM":'version'
}
#引用版本规则
from rest_framework.versioning import QueryParameterVersioning
class UserView():
    versioning_class = QueryParameterVersioning
    def get(self,request,*args,**kwargs):
        print(request.version)
        return

 十、解释器

from rest_framework.parsers import JSONParser,FormParser
#JSON解释器,POST解释器,
parser_classes = [JSONParser,FormParser]

请求头:

  • User-Agent:产生请求的浏览器类型。
  • Accept:客户端可识别的内容类型列表。
  • Host:请求的主机名,允许多个域名同处一个IP地址,即虚拟主机。

状态码:

  • 1xx:指示信息--表示请求已接收,继续处理。
  • 2xx:成功--表示请求已被成功接收、理解、接受。
  • 3xx:重定向--要完成请求必须进行更进一步的操作。
  • 4xx:客户端错误--请求有语法错误或请求无法实现。
  • 5xx:服务器端错误--服务器未能实现合法的请求。

请求方法:

十一、序列化

  1.基础用法

#序列化方法函数
from rest_framework import serializers
class UserINfoSerializer(serializers.Serializer):
    #带choise的序列化
    x1 = serializers.CharField(source="user_type")
    #直接获得choise的中文内容
    x2 = serializers.CharField(source="get_user_type_display")
    #正常的序列化
    username = serializers.CharField()
    #一对多
    gp = serializers.CharField(source="group.title")
    #多对多
    rls = serializers.SerializerMethodField()#自定义显示
    def get_rls(self,row):
        role_obj_list = row.roles.all()
        ret = []
        for item in role_obj_list:
            ret.append({"id":item.id,"title":item.title})
        return  ret

#引入序列化
class UserInfoView(APIview):
    def get(self,request,*args,**kwargs):
        user = models.UserInfo.object.all()
        ser = UserINfoSerializer(instance=user,many=True)
        ret = json.dumps(ser.data,ensure_ascii=False)
        return HttpResponse(ret)

  2.使用自带的序列化方法

#序列化方法函数
from rest_framework import serializers
class UserINfoSerializer(serializers.ModelSerializer):    
    class Meta:
        model = models.UserInfo
        #获取所有的内容
        #fields = "__all__"
        #自定义获取的内容
        fields = ['id','username']
        depth = 0 #获取到的层级 0-10
#使用序列化方法        
class UserInfoView(APIView):
    def get(self,request,*args,**kwargs):
        users = models.UserInfo.objcet.all()
        ser = UserINfoSerializer(instance=users,many=True,context={'request':request})
        ret = json.dumps(ser.data,ensure_ascii=False)
        return HttpResponse(ret)

  3.序列化验证

#验证方法
from rest_framework import serializers
class XXValidator(object):
    def __init__(self,base):
        self.base = base
        
    def __call__(self,value):
        if not value.startswith(self.base):
            message = 'XXX的%s错误' % self.base
            raise serializers.ValidationError(message)
#引入验证方法       
class UserGroupSerializer(serializers.Serializer):
    title = serializers.CharField(error_messages={'required':'XXX问题'},validators=[XXValidator('内容'),])

十二、分页

from rest_framework.views import APIView
from rest_framework.pagination import PageNumberPagination
#自定义显示内容
class MypageNumberPagination(PageNumberPagination):
    page_size = 2 #每页显示的内容
    page_query_param = 'page'#key值
#只用自定义显示的内容    
class PagerView(APIView):
    def get(self,request,*args,**kwargs):
        #获取所有数据
        roles = models.Role.object.all()
        #创建分页对象
        pg = PageNumberPagination()
        #获取分页数据
        pager_roles = pg.MypageNumberPagination(queryset=roles,request=request,view=self)
        #对数据进行序列化,PagerSerialiser的方法,需要自定义
        ser = PagerSerialiser(instance=pager_roles,many=True)
        #返回基础数据
        #return Response(ser.data)
        #返回带上一页,下一页地址的数据
        return pg.get_paginated_response(ser.data)

 

posted @ 2019-07-30 10:03  澄心元素  阅读(...)  评论(... 编辑 收藏