翼度科技»论坛 编程开发 python 查看内容

drf 认证组件、权限组件、频率组件

7

主题

7

帖子

21

积分

新手上路

Rank: 1

积分
21
认证组件
  1. 访问某个接口 需要登陆后才能访问
  2. #第一步 写一个登录功能 用户表
  3.         User表
  4.     UserToken表 :存储用户登录状态 【这个表可以没有 如果没有 把字段直接卸载User表上也可以】
复制代码
登录接口

model.py
  1. class Books(models.Model):
  2.     name = models.CharField(max_length=32)
  3.     price = models.CharField(max_length=32)
  4.     publish = models.ForeignKey(to='Publish',on_delete=models.CASCADE)
  5.     authors = models.ManyToManyField(to='Authors')
  6.     def publish_dict(self):
  7.         return {'name':self.publish.name,'addr':self.publish.addr}
  8.     def author_list(self):
  9.         l = []
  10.         for author in self.authors.all():
  11.             l.append({'name':author.name,'phone':author.phone})
  12.         return l
  13. class Publish(models.Model):
  14.     name = models.CharField(max_length=32)
  15.     addr = models.CharField(max_length=32)
  16. class Authors(models.Model):
  17.     name = models.CharField(max_length=32)
  18.     phone = models.CharField(max_length=32)
  19. class User(models.Model):
  20.     username = models.CharField(max_length=32)
  21.     password = models.IntegerField()
  22. class UserToken(models.Model):
  23.     token = models.CharField(max_length=32)
  24.     user = models.OneToOneField(to='User',on_delete=models.CASCADE,null=True)
复制代码
url.py
  1. router = SimpleRouter()
  2. router.register('user',views.UserView,'user')
  3. urlpatterns = [
  4.     path('admin/', admin.site.urls),
  5.     path('api/v1/', include(router.urls))
  6. ]
复制代码
views.py
  1. import uuid
  2. from django.shortcuts import render
  3. from .models import User, UserToken
  4. from rest_framework.viewsets import ModelViewSet,ViewSet
  5. from rest_framework.decorators import action
  6. from rest_framework.response import Response
  7. # Create your views here.
  8. class UserView(ViewSet):
  9.     @action(methods=['POST'], detail=False)
  10.     def login(self, request):
  11.         username = request.data.get('username')
  12.         password = request.data.get('password')
  13.         user = User.objects.filter(username=username, password=password).first()
  14.         if user:
  15.             token = str(uuid.uuid4())
  16.            #用户登陆成功随机生成一个用不重复的字符串
  17.                 #在Usertoken表中存储一下 :1 从来没有登陆过 插入一条 2登陆过 修改记录
  18.         UserToken.objects.update_or_create(user=user, defaults={'token': token})
  19.             #如果有就修改 没有就新增
  20.             #kwargs 传入的东西查找 能找到 使用defaults的更新 否则新增一条
  21.             return Response({'code': 100, 'msg': '登陆成功', 'token': token})
  22.         else:
  23.             return Response({'code': 101, 'msg': '用户名或密码错误'})
  24.    
  25. '''
  26. 以后 有的接口组要登录后才能访问 有的接口不登陆就能访问(查询所有不需要登录就能访问 查询单个 需要登陆才能访问)
  27.         登录认证的限制
  28.        
  29. 写登录接口 返回token 以后只要带着token过来 就是登陆了 不带就是没有登陆
  30. '''
复制代码
认证组件使用
  1. # 查询所有不需要登录就能访问
  2. # 查询单个,需要登录才能访问
  3. # 在查询单个个视图类中写authentication_classes=[]
复制代码
1.写一个认证类 需要继承BaseAuthentication
  1. from rest_framework.authentication import BaseAuthentication
复制代码

2.通过看源码分析 必须重写authenticate方法 在该方法中实现登录认证
3.如果认证成功 返回两个值【登录用户和token或None】
4.认证不通过 抛异常
  1. from rest_framework.exceptions import AuthenticationFailed
复制代码
5.局部使用和全局使用
局部:只在某视图类中使用【当前视图类管理的所有接口均使用过】
  1. class BookView(ViewSetMixin,RetrieveAPIView):
  2.     queryset = Books.objects.all()
  3.     serializer_class = BooksSerializers
  4.     authentication_classes = [LoginAuth]
  5.     '''登录以后才能查询单个书信息'''
复制代码
全局:全部接口都生效(登录接口不需要)
  1. REST_FRAMEWORK={
  2. 'DEFAULT_AUTHENTICATION_CLASSES': ['app01.authentication.LoginAuth']
  3. }
  4. '''
  5. 所有接口都需要认证 登陆不能验证 局部禁用
  6. '''
复制代码
局部禁用:
  1. class UserView(ViewSet):
  2.     authentication_classes = []
复制代码
view.py
  1. #查所有
  2. class BooksView(ViewSetMixin,ListAPIView):
  3.     queryset = Books.objects.all()
  4.     serializer_class = BooksSerializers
  5. #查单个
  6. class BookView(ViewSetMixin,RetrieveAPIView):
  7.     queryset = Books.objects.all()
  8.     serializer_class = BooksSerializers
  9.     authentication_classes = [LoginAuth] #需要写一个认证类
复制代码
authentication.py 认证类代码
  1. #自己写的认证类 需要继承某个类
  2. from .models import UserToken
  3. from rest_framework.authentication import BaseAuthentication
  4. from rest_framework.exceptions import AuthenticationFailed
  5. class LoginAuth(BaseAuthentication):
  6.     def authenticate(self,request):
  7.         #在这里实现用户的验证 如果是登录的继续走 不是就抛异常
  8.         #请求中是否携带token判断是否登录 地址栏中 request是新的
  9.         token = request.query_params.get('token',None)
  10.         if token: #前端传入token 去表中查 如果查到了登录了返回两个值 固定的 1.当前登录用户 2.token
  11.             user_token=UserToken.objects.filter(token=token).first()
  12.             if user_token:
  13.                 return user_token.user,token
  14.             else:
  15.                 raise AuthenticationFailed('token认证失败')#没登陆就抛异常
  16.         else:
  17.             raise AuthenticationFailed('token没传')
复制代码
权限组件
  1. 即便登陆成功 有些接口 还是不能访问 因为没有权限
  2. 登陆后 有的接口有访问权限 有的没有
  3. 查询单个和查询所有 都要登录才能访问 -- 全局认证
  4.         查询单个需要超级管理员
  5.     查询所有需要登陆的用户
  6.    
  7. 权限是一个字段 在User表中加入user_type
  8. 字段
复制代码
权限的使用

1.写一个权限类 继承BasePermission
  1. from rest_framework.permissions import BasePermission
复制代码
2.重写has_permission方法 在该方法实现权限认证 在这方法中request.user就是当前登录用户

3.如果有权限 返回True
4.如果没有权限 返回False 定制返回中文 self.message = '中文'
5.局部使用和全局使用
局部:只在某个视图类中使用【当前视图类管理的所有接口都使用
  1. class BookView(ViewSetMixin,RetrieveAPIView):
  2.     queryset = Books.objects.all()
  3.     serializer_class = BooksSerializers
  4.     authentication_classes = [LoginAuth] #需要写一个认证类
  5.     permission_classes = [CommonPermission] #认证和权限都可以加多个 多层
复制代码
全局:全局所有接口都生效
  1. 'DEFAULT_PERMISSION_CLASSES': ['app01.permissions.CommonPermission'],
复制代码
局部禁用:
  1. permission_classes = []
复制代码
views.py
  1. class BookView(ViewSetMixin,RetrieveAPIView):
  2.     queryset = Books.objects.all()
  3.     serializer_class = BooksSerializers
  4.     authentication_classes = [LoginAuth] #需要写一个认证类
  5.     permission_classes = [CommonPermission] #认证和权限都可以加多个 多层
复制代码
permission.py
  1. #权限类  写一个类 重写方法 在方法中实现权限认证
  2. from rest_framework.permissions import BasePermission
  3. class CommonPermission(BasePermission):
  4.     #重写has_permission方法 有权限返回True,没有权限返回False
  5.     def has_permission(self,request,view):
  6.         #实现权限的控制  -- 要先知道当前的登录用户是谁 request.user 前面认证返回的登录用户 就是这里的request.user
  7.         if request.user.user_type == 1:
  8.             return True
  9.         else:
  10.             #没有权限 可以放一个message
  11.             self.message = '您是%s 您没有权限' %request.user.get_user_type_display()
  12.             return False
复制代码
频率组件
  1. 控制某个接口访问频率(次数)
  2. 查询所有接口 同一个ip一分钟只能访问5次
复制代码
使用步骤

1.写一个频率类 继承SimpleRateThrottle
  1. from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
复制代码
2.重写get_cache_key方法 返回什么 就以什么做限制 先用ip
  1. #客户端的ip地址 从哪里拿 HttpRequest.META里取
  2. return request.META.get('REMOTE_ADDR')
复制代码
3.配置一个类属性
  1. scope = 'lzy'
复制代码
4.在配置文件中配置
  1. 'DEFAULT_THROTTLE_RATES': {
  2.         'lzy': '5/m',
  3.     },
复制代码
5.局部使用和全局使用
局部:只在某个视图类中使用【当前视图类管理的所有接口都使用
  1.     throttle_classes = [CommonThrottle]
复制代码
全局:全局所有接口都生效
  1. 'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle'],
复制代码
局部禁用:
  1.     throttle_classes = []
复制代码
过滤排序

必须继承GenericAPIView及其子类才能使用这种方式
只有查所有才用到过滤
内置过滤类的使用 继承GenericAPIView
  1. #查所有
  2. class BooksView(ViewSetMixin,ListAPIView):
  3.     queryset = Books.objects.all()
  4.     serializer_class = BooksSerializers
  5.     #这样就有过滤功能
  6.     filter_backends = [SearchFilter]
  7.     search_fields = ['name']  #按照名字模糊匹配 内置的 固定用法
  8.     search_fields = ['name','price']  #按照名字或价格模糊匹配  其中有一个是相同的都会被筛选出来
  9. ulr = 127.0.0.1:8000/api/v1/books/?seach=书
复制代码
使用第三方django-filter实现过滤
  1. # 安装:django-filter
  2. #查所有
  3. class BooksView(ViewSetMixin,ListAPIView):
  4.     queryset = Books.objects.all()
  5.     serializer_class = BooksSerializers
  6.     #这样就有过滤功能
  7.     filter_backends = [DjangoFilterBackend]
  8.     filterset_fields = ['name'] #支持完整匹配 name=书
  9.    
  10. url = 127.0.0.1:8000/api/v1/books/?name=书2
  11. url = 127.0.0.1:8000/api/v1/books/?name=书2&price=12  
复制代码
自己定制过滤类实现过滤
  1. 查询价格大于100的书
  2. url = http://127.0.0.1:8000/api/v1/books/?price_gt=100
  3.       
复制代码
1.定义一个过滤类 继承BaseFilterBackend
  1. from django_filters.rest_framework import DjangoFilterBackend
复制代码
2.重写filter_queryset方法
  1. def filter_queryset(self,request, queryset, view):
  2.     price_gt = request.query_params.get('price_gt',None)
  3.     if price_gt:
  4.         qs=queryset.filter(price__gt=int(price_gt))
  5.         return qs
  6.     else:
  7.         return queryset
复制代码
3.配置在视图类
  1. filter_backends = [CommentFilter]
  2. '''可以定制多个 从左往右 依次执行'''
复制代码
排序的使用
  1. 内置
  2. from rest_framework.filters import OrderingFilter
  3.     filter_backends = [OrderingFilter,CommentFilter]
  4.     ordering_fields = ['price']
  5.     #按照价格排序
  6.    
  7. 支持查询的方法
  8.         http://127.0.0.1:8000/api/v1/books/?ordering=price
  9.     http://127.0.0.1:8000/api/v1/books/?ordering=-price
  10.    http://127.0.0.1:8000/api/v1/books/?ordering=-id,pric
复制代码
分页

只有查询才有分页
drf内置了三个分页器 之前的东西一样用
第一种:PageNumberPagination
  1. from rest_framework.pagination import LimitOffsetPagination,CursorPagination,PageNumberPagination
  2. class CommonPageNumberPagination(PageNumberPagination):
  3.     page_size = 1 #每页显示两条
  4.     page_query_param = 'page' #page=10 查询第10也的数据
  5.     page_size_query_param = 'size' # page=10&size=5 查询第十页 每页显示5条
  6.     max_page_size = 10   #每页最大的显示条数
  7.    
  8.     #配置在试图页即可
  9.    
  10.     pagination_class = CommonCursorPagination
复制代码
第二种:LimitOffsetPagination
  1. from rest_framework.pagination import LimitOffsetPagination,CursorPagination,PageNumberPagination
  2. class CommonPageNumberPagination(LimitOffsetPagination):
  3.     default_limit = 3 #每页显示3条
  4.     limit_query_param = 'limit' #limit=3
  5.     offset_query_param = 'offset' #offset=1 从第一个位置开始 取limit条
  6.     max_limit = 5
  7.    
  8.     #配置在试图页即可
  9.    
  10.     pagination_class = CommonCursorPagination
复制代码
app用
  1. class CommonPageNumberPagination(CursorPagination):
  2.     cursor_query_param = 'cursor'  #查询参数
  3.     page_size = 2 #每页多少条
  4.     ordering = 'id'  #排序字段
  5.     #配置在试图页即可
  6.    
  7.     pagination_class = CommonCursorPagination
  8. #游标分页 只能下一页 上一页 不能跳到中间 但他的效率最高 大数据量分页 使用这种较好
复制代码
来源:https://www.cnblogs.com/lzy199911/p/17101878.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具