本文最后更新于:3 years ago

Django rest framework

基础构建

首先startapp api

接着将rest_framework,api注册到app中

之后

#setting.py
REST_FRAMEWORK = {
    'DEFAULT_PERMISSION_CLASSES': [
        'rest_framework.permissions.IsAdminUser',
    ], #配置全局权限
    'DEFAULT_AUTHENTICATION_CLASSES':[], #配置全局认证
    'PAGE_SIZE': 10
}
#局部的view.py可以设置空的认证
authentication_classes = []

认证

CBV 模式

请求进来先执行dispatch,接着执行请求方式

token 实现基本认证

首先要创建两张表
#view.py
from django.shortcuts import render,HttpResponse
from rest_framework.views import APIView
from rest_framework.authentication import BasicAuthentication
from rest_framework import exceptions
import json

def get_token_code(username):
    """
    根据用户名和时间戳来生成永不相同的token随机字符串
    :param username: 字符串格式的用户名
    :return: 字符串格式的Token
    """

    import time
    import hashlib

    timestamp = str(time.time())
    m = hashlib.md5(username.encode("utf-8"))
    # md5 要传入字节类型的数据
    m.update(timestamp.encode("utf-8"))
    return m.hexdigest()  # 将生成的随机字符串返回

class GoodsView(APIView):

    authentication_classes = [MyAuthentication,]
    def get(self,request):
        ret = {
            'code':1000,
            'msg':'xxx'
        }
        return HttpResponse(json.dumps(ret))
    
class AuthView(APIView):
	'''
	用户登录
	'''
    authentication_classes = []
    def post(self,request,*args,**kwargs):
        data = request.POST
        print(data)
        username = data['username']
        password = data['password']
        user = models.User.objects.filter(username=username,password=password).first()
        if not user:
            return HttpResponse(json.dumps({'code':1002,'message':'登录失败'}))
        else:
            res = {'code':1000}
            token = get_token_code(username)
            models.UserToken.objects.update_or_create(user=user,defaults={"token":token})
            res['token'] = token
            return HttpResponse(json.dumps(res))
#auth.py
from rest_framework import exceptions
from rest_framework.authentication import BaseAuthentication
from users import models
class MyAuthentication(BaseAuthentication):
    '''
    用户认证
    '''
    def authenticate(self, request):
        meth = request.method
        token = request.data.get('token')  # _request是原生的request
        token_obj = models.UserToken.objects.filter(token=token).first()
        if not token:
            raise exceptions.AuthenticationFailed('用户认证失败')
        return (token_obj.user,token)

    def authenticate_header(self, val):
        pass

权限

#permisssion.py
from rest_framework import permissions
from rest_framework.permissions import BasePermission

class MyPermission(BasePermission):

    def has_permission(self, request, view):
        if request.user.gender == '女':
            return False #无权限
        return True #有权限

频率

#throttle.py
from rest_framework.throttling import BaseThrottle
import time

VISIT_RECORD = {}
class AuthThrottle(BaseThrottle):
    def allow_request(self, request, view):
        #获取ip地址
        remote_addr = self.get_ident(request)
        ctime = time.time()
        if remote_addr not in VISIT_RECORD:
            VISIT_RECORD[remote_addr] = [ctime,] #将ip地址存入
            return True #return False 表示访问频率太高被限制
        history = VISIT_RECORD.get(remote_addr)
        history.insert(0,ctime)
        while history and history[-1] < ctime - 60:
            history.pop()
        if len(history) < 3:
            return True
    def wait(self):
        '''还需要等待多长时间'''
        ctime = time.time()
        return 60 - (ctime - self.history[-1])
内置访问频率
#setting.py
REST_FRAMEWORK = {
    'DEFAULT_THROTTLE_CLASSES':[],#配置全局频率
    'DEFAULT_THROTTLE_RATES':{
        'wyc':'3/m' #每分钟三次 ,'wyc' 需要设置 scope
    },
}
#throttle.py
from rest_framework.throttling import SimpleRateThrottle
class MyThrottle(SimpleRateThrottle):
    scope = 'wyc' #全局配置中的key
    def get_cache_key(self, request, view):
        return self.get_ident(request)

版本

1.通过get传参
#setting.py
REST_FRAMEWORK = {
    'DEFAULT_VERSION':'v1',
    'ALLOWED_VERSION':['v1','v2'],
    'VERSION_PARAM':'version'
}
#自定义
from rest_framework.versioning import BaseVersioning

class ParamVersion(BaseVersioning):
    def determine_version(self, request, *args, **kwargs):
        version = request.query_params.get('version') #传入version参数
        return version

versioning_class = ParamVersion
#内置
from rest_framework.versioning import QueryParameterVersioning
versioning_class = QueryParameterVersioning
2.通过路由
#urls.py
REST_FRAMEWORK = {
    'DEFAULT_VERSIONING_CLASS':"rest_framework.versioning.URLPathVersioning",
    'DEFAULT_VERSION':'v1',
    'ALLOWED_VERSION':['v1','v2'],
    'VERSION_PARAM':'version'
}

解析器

#全局配置
REST_FRAMEWORK = {
    'DEFAULT_PARSER_CLASSES':		 ['rest_framework.parsers.JSONParser','rest_framework.parsers.FormParser'],
    
}
from rest_framework.parsers import JSONParser,FormParser
class ():
     parser_classes = [JSONParser,FormParser]
     '''
     	JSONParser:
            允许用户发json格式数据
            a.content-type:application/json
            b.request.data获取数据
       	FormParser:
       		a.content-type:application/x-www-form-unlencoded头
       		b.可以用request.data获取数据
     '''
在APIView中封装的request,就实现了请求数据的解析:

对于GET请求的参数我们通过request.query_params来获取。

对于POST请求、PUT请求的数据我们通过request.data来获取。

序列化

#urls.py对单个数据查询
url(r'goods/(?P<pk>\d+)$',views.GoodsView.as_view()),
class GoodsView(APIView):
    def get(self,request,*args,**kwargs):
        print(request.user,request.auth)
        pk = kwargs.get('pk')
        goods = models.Goods.objects.filter(id=pk).first()
        ser = serializer.GoodsSerializer(goods,many=False)
        return Response(ser.data)

#serializer.py
from rest_framework import serializers
from users import models
class GoodsSerializer(serializers.ModelSerializer):

    class Meta:
        models = models.Goods
        fields = "__all__"
        depth = 0 #深度用来查看外键表的数据
#view.py
class GoodsView(APIView):
    def get(self,request):
        print(request.user,request.auth)
        goods = models.Goods.objects.all()
        ser = serializer.GoodsSerializer(goods,many=True)
        return Response(ser.data)
#校验
class GoodsSerializer(serializers.Serializer):
    title = serializers.CharField(error_messages={'required':'标题不能为空'})
class GoodsView(APIView):
    def post(self,request,*args,**kwargs):
        ser = serializer.GoodsSerializer(data=request.data)
        if ser.is_valid():
            print(ser.validated_data)
        else:
            print(ser.errors)

视图

#url.py
url(r'^good/$',views.GenView.as_view({'get':'list','post':'create'})),
url(r'^good/(?P<pk>\d+)/$',views.GenView.as_view({'get':'retrieve','put':'update','delete':'destroy','patch':'partial_update','post':'create'})),
#view.py
from rest_framework.viewsets import ModelViewSet
from rest_framework.pagination import PageNumberPagination
class GenView(ModelViewSet):
    authentication_classes = []
    queryset = models.Goods.objects.all()
    serializer_class = serializer.GoodsSerializer
    pagination_class = PageNumberPagination

路由

#url.py
from rest_framework import routers
router = routers.DefaultRouter()
router.register(r'good',views.GenView)

urlpatterns = [
    url(r'',include(router.urls)) #自动添加view相关的路由,四个
]

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

python gui界面和pygame库 Previous
Django基础配置和知识 Next