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  # 配置我们自己写的分页类

  

 

posted @ 2019-07-31 20:09  Py浪涛  阅读(69)  评论(0编辑  收藏  举报
你想听歌吗o((;=゚ 3゚ =))o~♪