本文最后更新于:4 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 协议 ,转载请注明出处!