认证、权限、视图组件

drf组件

认证组件

models.py

class User(models.Model):
    name = models.CharField(max_length=32)
    pwd = models.CharField(max_length=32)
    user_type = models.IntegerField(choice=(1,'超级管理员'),(2,'普通管理员'),(3,'用户'))
 
#token跟uesr表做一对一关联
class Token(models.Model):
    user = models.OneToOneField(to='User')
    token = models.CharField(max_length=32)

views.py

from rest_framewoke.views import APIView
import uuid

class Login(APIView):
    def post(self,request):
        response = {'code':100,'msg':'登入成功'}
        name = request.data.get('name')
        pwd = request.data.get('pwd')
        try:
            user = models.User.objects.filter(name=name,pwd=pwd).get()
            #登入成功需要去token表中存数据,生成一个唯一的id
            token = uuid.uuid4()
            #有则更新,没有则创建
            models.Token.objects.update_or_create(user=user,defaults = {'token':token})
            response['token'] = token
        except ObjectDoesNotExist as e:
            response['code'] = 101
            response['msg'] = '用户名或密码错误'
        except Exception as e:
            response['code'] = 102
            response['msg'] = str(e)
        return Response(response)

新建认证类

from rest_framework.authentication import BaseAuthentication
from rest_framwork.exceptions import AuthenticationFailed
from app01 import models

class TokenAuth(BaseAuthentication):
    #认证类中的方法
    def authenticate(self,request):
        token = request.GET.get('token')
        token_obj = models.Token.objects.filter(token=token).first()
        if token_obj:
            #token_obj.user当前登入对象
            return token_obj.user,token_obj
        else:
            raise AuthenticationFailed('请先登入')

认证组件的使用

局部使用

from app01.MyAuth import TokenAuth
class Books(APIView):
    #可以写多个认证类
    authentication_classes = [TokenAuth,]
    def get(self,request):
        pass

全局使用

#在settings中配置
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.TokenAuth',]  # app01.文件名.类名
}

局部禁用

from app01.MyAuth import TokenAuth
class Books(APIView):
    authentication_classes = []
    def get(self,request):
        pass

根据源码可以知道:

  • 如果在项目中的settings中配置了REST_FRAMEWORK,默认先从项目中的settings中取
  • 如果取不到,就去默认的drf配置文件中取
  • 如果在视图类中配置了,先去视图中配置的取

总结:

先取视图类中配置的=>项目settings中取=>默认配置

权限组件

新建一个权限类,继承BasePermission

from rest_framework.permission import BasePermission

class MyPermission(BasePermission):
    message = '不是超级用户,查看不了'  #将错误信息以中文的信息展示
    #因为权限在认证之后执行的,所有能拿到request.user
    def has_permission(self,request,view):
        if request.user.user_type==1:
            return True
        else:
            return False

权限组件的使用

局部使用

from app01.MyAuth import TokenAuth
class Books(APIView):
    permission_classes = [MyPermission,]
    def get(self,request):
        pass

全局使用

#在settings中配置
REST_FRAMEWORK = {
    'DEFAULT_AUTHENTICATION_CLASSES':['app01.MyAuth.TokenAuth',],  # 应用名.文件名.类名
    'DEFAULT_PERMISSION_CLASSES':['app01.MyAuth.MyPermission']
}

局部禁用

from app01.MyAuth import MyPermission
class Books(APIView):
    permission_classes = []
    def get(self,request):
        pass

视图组件

基于mixins来封装的视图

第一种

url部分

url(r'^publish/$', views.PublishView.as_view()),
url(r'^publish/(?P<pk>\d+)/$', views.PublishDetailView.as_view()),
from rest_framework.mixins import CreateModelMixin,ListModelMixin,RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin
from rest_framework.generics import GenericAPIView

class PublishView(CreateModelMixins,ListModelMixin,GenericAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers
    def post(self,request,*args,**kwargs):
        return self.create(request,*args,**kwargs)
    def get(self,request,*args,**kwargs):
        return self.list(request,*args,**kwargs)
class PublishDetailView(RetrieveModelMixin,DestroyModelMixin,UpdateModelMixin,GenericAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers
    def get(self,request, *args, **kwargs):
        return self.retrieve(request, *args, **kwargs)
    def put(self,request, *args, **kwargs):
        return self.update(request, *args, **kwargs)
    def delete(self,request, *args, **kwargs):
        return self.destroy(request, *args, **kwargs)

第二种

from rest_framework.generics import CreateAPIView,ListCreateAPIView,DestroyAPIView,RetrieveUpdateDestroyAPIView
class PublishView(ListCreateAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers

class PublishDetailView(RetrieveUpdateDestroyAPIView):
    queryset = models.Publish.objects.all()
    serializer_class = PublishSerializers

第三种

url部分

 url(r'^publish/$', views.PublishView.as_view({'get': 'list', 'post': 'create'})),
    url(r'^publish/(?P<pk>\d+)/$',views.PublishView.as_view({'get': 'retrieve', 'put': 'update', 'delete': 'destroy'})),
from rest_framework.viewsets import ModelViewSet
class PublishView(ModelViewSet):
    queryset=models.Publish.objects.all()
    serializer_class=PublishSerializers

自定义

url部分

url(r'^aa/$', views.PublishView.as_view({'get': 'aaa'})),
from rest_framework.viewsets import  ViewSetMixin
from rest_framework.views import  APIView
# ViewSetMixin 重写了as_view方法
class Test(ViewSetMixin,APIView):  #注意先后顺序,因为APIView中也有as_view方法

    def aaa(self,request):
        return Response()

ModelViewSet:继承了

  • mixins.CreateModelMixin
  • mixins.RetrieveModelMixin
  • mixins.UpdateModelMixin
  • mixins.DestroyModelMixin
  • mixins.ListModelMixin
  • GenericViewSet

RetrieveUpdateDestroyAPIView:继承了

class RetrieveUpdateDestroyAPIView(mixins.RetrieveModelMixin,
                                   mixins.UpdateModelMixin,
                                   mixins.DestroyModelMixin,
                                   GenericAPIView):

ListCreateAPIView:继承了

class ListCreateAPIView(mixins.ListModelMixin,
                        mixins.CreateModelMixin,
                        GenericAPIView):

了解

JWT:是JSON格式的被加密了的在字符串,服务器不保存session数据,所有数据都保存在客户端,每次请求都发回服务器

django的OneToOneField源码:本质就是继承了ForeignKey,初始化的时候kwargs['unique'] = True

posted @ 2019-07-03 22:27  ymg-颜  阅读(151)  评论(0编辑  收藏  举报