RestFramework的其他组件(三)
1.认证组件
说明:认证组件就是判断用户是不是登陆状态
#代码:
#首先登陆
views.py
class Login(APIView):
res_msg = {"code":None,"userinfo":None,"token":None,"msg":None}
def post(self,request):
username = request.data.get('username')
password = request.data.get('password')
user_obj= models.User.objects.filter(username=username,password=password).first()
if user_obj:
random_str = uuid.uuid4()
models.UserToken.objects.update_or_create(
user=user_obj,
defaults={
'token':random_str,
}
)
self.res_msg["code"] = 0
self.res_msg["userinfo"] = username
self.res_msg["token"] = random_str
self.res_msg["msg"] = '登陆成功'
else:
self.res_msg["code"]=1
self.res_msg["msg"] = "登陆失败"
return Response(self.res_msg)
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.authentication import BaseAuthentication
class UserAuthToken(BaseAuthentication):
def authenticate_header(self,request):
pass
def authenticate(self,request):
token = request.query_params.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
print(token_obj)
if token_obj:
return token_obj.user,token
else:
raise AuthenticationFailed('认证失败')
认证组件的使用:
class AuthorHandel(ModelViewSet):
authentication_classes =[UserAuthToken,]
queryset = models.Author.objects.all()
serializer_class = AuthorSerializer
配置为全局的认证组件:
app01\utils\auth.py
#写入:
from rest_framework.exceptions import AuthenticationFailed
from rest_framework.authentication import BaseAuthentication
from app01 import models
class UserAuthToken(BaseAuthentication):
def authenticate_header(self, request):
pass
# authenticate方法固定的,并且必须有个参数,这个参数是新的request对象,不信,看源码
def authenticate(self, request):
token = request.query_params.get('token')
token_obj = models.UserToken.objects.filter(token=token).first()
if token_obj:
return token_obj.user,token
else:
raise AuthenticationFailed('认证失败')
views.py
from app01.utils.auth import UserAuthToken
class PublishHandel(ModelViewSet):
authentication_classes = [UserAuthToken, ] # 处理认证的
permission_classes = [UserPer, ] # 处理权限的
queryset = models.Publish.objects.all()
serializer_class = PublishSerializer
settings.py
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.utils.auth.UserAuthToken",] , #里面是路径字符串
"DEFAULT_THROTTLE_RATES":{
"xxx":"5/m",
}
}
2.权限组件
说明:权限组件就是判断用户有没有权限访问
代码:
views.py
from rest_framework.permissions import BasePermission
class UserPer(BasePermission):
message = "SVIP才能访问!"
#view 代表在view组件里面使用UserPer nameview就是那个view
# request 只有通过认证之后才可以使用权限组件,因为认证过后会对request重新封装
def has_permission(self, request,view):
#print(request.user.usertype)
if request.user.usertype == 3:
return True # 通过权限
return False # 没有通过
权限组件的使用:
#那么那个view 就是PublishHandel
class PublishHandel(ModelViewSet):
authentication_classes = [UserAuthToken, ] # 处理认证的
permission_classes = [UserPer, ] # 处理权限的
queryset = models.Publish.objects.all()
serializer_class = PublishSerializer
3.频率限制组件
说明:就是控制用户访问的频率,可以防止恶意攻击,可以简单的防止爬虫
第一种,重写限制频率的代码:
views.py
from rest_framework.throttling import BaseThrottle, SimpleRateThrottle
import time
visit_record = {}
class VisitThrottle(BaseThrottle):
# 限制访问的时间
VIST_TIME = 10
VISIT_COUNT = 3
def allow_request(self, request, view):
id = request.META.get('REMOTE_ADDR')
self.now = time.time()
if id not in visit_record:
visit_record[id] = []
self.history = visit_record[id]
while self.history and self.now - self.history[-1] > self.VIST_TIME:
self.history.pop()
if len(self.history) >= self.VISIT_COUNT:
return False
else:
self.history.insert(0, self.now)
return True
def wait(self):
return self.history[-1] + self.VIST_TIME - self.now
使用频率限制组件
class BookHandel(ModelViewSet):
throttle_classes = [VisitThrottle,] # 处理频率的
queryset = models.Book.objects.all()
serializer_class = BookSerializer
第二种:
直接使用提供的简单的频率限制组件:
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
class VisitThrottle(SimpleRateThrottle):
scope = 'xxx' // 这个就是一个名字 在setting文件里面配置是需要指定这个名字找到
def get_cache_key(self, request, view):
return self.get_ident(request)
settings.py 文件里面写入:
REST_FRAMEWORK ={
"DEFAULY_THROTTLE = {
'xxx':'5/m' # 对应上面的scope 5/m 限制每分钟访问5次
}
}
4.URL生成器
URL生成器的使用:
urls.py
router = routers.DefaultRouter() router.register('authors',views.SAuthorHandle) urlpatterns = [ url(r'^', include(router.urls)), ]
使用这个生成器的缺陷:
只能使用views.py 这种形式:
class AuthorHandel(ModelViewSet):
authentication_classes = [UserAuthToken, ]
queryset = models.Author.objects.all()
serializer_class = AuthorSerializer
5.分页组件
分页组件的使用:配置全局的
#引入分页
from rest_framework.pagination import PageNumberPagination
class BookView(APIView):
# 通过源码看,认证类的查找过程,和解析组件的查找过程是一样的
# authentication_classes = [UserAuth,]
# throttle_classes = [VisitThrottle,]
def get(self,request):
'''
查看所有书籍
:param request:
:return:
'''
book_obj_list = models.Book.objects.all()
#创建分页器对象,PageNumberPagination类中除了PAGE_SIZE属性之外,还有个page属性,这个page属性是第几页,用法是http://127.0.0.1:8000/books/?page=1
pnb = PageNumberPagination()
#通过分页器对象的paginate_queryset方法进行分页,
paged_book_list = pnb.paginate_queryset(book_obj_list,request,)
#将分页的数据进行序列化
s_books = BookSerializers(paged_book_list,many=True)
return Response(s_books.data)
settings.py 文件的配置
REST_FRAMEWORK={
# "DEFAULT_THROTTLE_RATES":{
# "visit_rate":"5/m",
# },
'PAGE_SIZE':5, #这是全局的一个每页展示多少条的配置,但是一般不用它,因为不用的数据展示可能每页展示的数量是不同的
}
非全局的使用:
#引入分页
from rest_framework.pagination import PageNumberPagination
class MyPagination(PageNumberPagination):
page_size = 3 #每页数据显示条数
page_query_param = 'pp' #http://127.0.0.1:8000/books/?pp=1,查询哪一页的数据
page_size_query_param = 'size' #如果我们显示的一页数据不够你用的,你想临时的多看展示一些数据,可以通过你设置的这个page_size_query_param作为参数来访问:http://127.0.0.1:8000/books/?pp=2&size=5 #那么你看到的虽然是第二页,但是可以看到5条数据,意思是将page_size的数字临时扩大了,每页展示的数据就多了或者少了,看你的page_size_query_param设置的值
max_page_size = 10 #最大每页展示多少条,即便是你前端通过page_size_query_param临时调整了page_size的值,但是最大也不能超过我们设置的max_page_size的值
class BookView(APIView):
def get(self,request):
'''
查看所有书籍
:param request:
:return:
'''
book_obj_list = models.Book.objects.all()
pnb = MyPagination()
paged_book_list = pnb.paginate_queryset(book_obj_list,request,)
s_books = BookSerializers(paged_book_list,many=True)
return Response(s_books.data)
在继承了ModelViewSet的写法:
#引入分页
from rest_framework.pagination import PageNumberPagination
class MyPagination(PageNumberPagination):
page_size = 3
page_query_param = 'pp' # 默认是page 在url上输入时的填写的参数
page_size_query_param = 'size'
max_page_size = 10
class BookHandel(ModelViewSet):
# renderer_classes = [] # 处理响应的
authentication_classes = [UserAuthToken, ] # 处理认证的
permission_classes = [UserPer, ] # 处理权限的
# parser_classes = [] # 将来在自己的写的视图类里面会加很多的类属性
# # 这些来属性就是那些组件对应的内容
throttle_classes = [VisitThrottle,] # 处理频率的
queryset = models.Book.objects.all()
serializer_class = BookSerializer
pagination_class = MyPagination # 配置我们自己写的分页类

浙公网安备 33010602011771号