认证组件
以后,有的接口需要登录后才能访问,有的接口,不登录就能访问
写一个登录接口,返回token,以后只要带着token过来,就是登录了 不带 就没有登录
需求:
查询所有不需要登录就能访问
查询单个 需要登录才能访问
认证组件使用步骤
1.写一个认证类,继承BaseAuthentication
2.重写authenticate方法,在该方法中实现登录认证:token在哪带的?如果认证它就是登录了
从地址栏中取request.query_params.get('token')
原生django,取出前端传入cookie,request.COOKIE.get('sessionid')
后期如果想从请求头中取 request.META.get('HTTP_TOKEN')
3.如果认证成功,返回两个值【返回None或两个值】第一个是token,或者返回None
4.认证不通过,抛异常AuthenticationFailed
5.局部使用和全局使用
局部:只在某个视图类中使用【当前视图类管理的所有接口】
from rest_framework.viewsets import ViewSetMixin
from rest_framework.generics import ListAPIView, RetrieveAPIView
from .authenticate import LoginAuth
class BookDetailView(ViewSetMixin, RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
全局:全局所有接口都生效(登录接口不要)
REST_FRAMEWORK = {'DEFAULT_AUTHENTICATION_CLASSES':['app01.authenticate.LoginAuth']
}
局部禁用:
class BookDetailView(ViewSetMixin, RetrieveAPIView):
authentication_classes = []
代码
视图
from rest_framework.viewsets import ViewSetMixin
from rest_framework.generics import ListAPIView, RetrieveAPIView
from .authenticate import LoginAuth
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookDetailView(ViewSetMixin, RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
认证类代码
from rest_framework.authentication import BaseAuthentication
from .models import UserToken
from rest_framework.exceptions import AuthenticationFailed
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
token = request.query_params.get('token', None)
if token:
user_token = UserToken.objects.filter(token=token).first()
if user_token:
return user_token.user, token
else:
raise AuthenticationFailed('token认证失败')
else:
raise AuthenticationFailed('token没传')
路由代码
from django.contrib import admin
from django.urls import path, include
from app01 import views
from rest_framework.routers import SimpleRouter, DefaultRouter
router = SimpleRouter()
router.register('user', views.UserView, 'user')
router.register('books', views.BookView, 'books')
router.register('books', views.BookDetailView, 'books')
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include(router.urls)),
]
坑
不要在配置文件中乱导入不使用的东西 否则会报错
权限组件
即便登录成功了,有些接口,还是不能访问,因为没有权限
登录后,有的接口有权限访问 有的没有权限访问
查询单个查询所有都要登录才能访问 ---》全局认证
查询单个需要超级管理员才能访问
查询所有,所有登录用户都能访问
权限是一个字段,在User表中,加入user_type字段
权限的使用
1.写一个权限类,继承BasePermission
2.重写has_permission方法,在该方法中实现权限认证,在这个方法中,request.user就是当前登录用户
ACL:访问控制列表
rbac:公司内部系统,基于角色的访问控制
abac:rbac升级版,加了属性认证
3.如果有权限,返回True
4.没有权限,返回False,定制返回的中文:self.message='中文'
5.局部使用和全局使用
局部:只在某个视图类中使用【当前视图类管理的所有接口】
class BookDetailView(ViewSetMixin, RetrieveAPIView):
permission_classes = [CommonPermission]
全局:全局所有接口都生效
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES': ['app01.permissions.CommonPermission',]}
局部禁用:
class BookDetailView(ViewSetMixin, RetrieveAPIView):
permission_classes = []
代码
需要增加一个user_type字段
权限类
from rest_framework.permissions import BasePermission
class CommonPermission(BasePermission):
def has_permission(self, request, view):
if request.user.user_type == 1:
return True
else:
self.message = '您是【%s】 您没有权限' % request.user.get_user_type_display()
return False
视图代码
from .permissions import CommonPermission
class BookDetailView(ViewSetMixin, RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = [CommonPermission]
频率组件
控制某个接口访问频率(次数)
查询所有接口,同一个ip一分钟只能访问5次
使用步骤
1.写一个频率类 继承SimpleRateThrottle
2.重写get_cache_key方法,返回什么就以什么限制---》ip 用户id做限制
3.配置一个类属性:scope = 'book_5_m'
4.在配置文件中配置
'DEFAULT_THROTTLE_RATES': {
'book_5_m': '5/m',
},
5 局部使用和全局使用
局部:只在某个视图类中使用【当前视图类管理的所有接口】
class BookDetailView(ViewSetMixin, RetrieveAPIView):
throttle_classes = [CommonThrottle]
全局:全局所有接口都生效
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES': ['app01.throttling.CommonThrottle'],}
局部禁用:
class BookDetailView(ViewSetMixin, RetrieveAPIView):
throttle_classes = []
频率代码
频率类
from rest_framework.throttling import BaseThrottle,SimpleRateThrottle
class CommonThrottle(SimpleRateThrottle):
scope = 'lqz'
def get_cache_key(self, request, view):
return request.user.pk
配置文件中的配置和属性scope有关
'DEFAULT_THROTTLE_RATES': {
'lqz': '5/m',
},
视图类代码
from .throttling import CommonThrottle
class BookDetailView(ViewSetMixin, RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
throttle_classes = [CommonThrottle]
过滤排序
restful规范中 要求了 请求地址中带过滤条件
5个接口中,只有一个接口需要有过滤和排序 查询所有接口
3种过滤方式(1.内置的:模糊匹配,2.第三方需要下载django—filter模块:精准匹配,3.自定义过滤类)
查询 所有图书接口 查询以 红 开头的所有图书
继承APIView 伪代码
class BookView(APIView):
def get(self,request):
search=request.query_params.get('search')
books=Book.objects.filter()
继承APIView如何写,完全自己写,麻烦,但是清晰
1.内置过滤类的使用【继承GenericAPIView】
from rest_framework.filters import SearchFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [SearchFilter]
search_fields = ['name','price']
可以使用的搜索方式
http://127.0.0.1:8000/api/v1/books/?search=红
'''
注意:过滤使用时前端的数据格式里面的字段都是根据序列化类里面的字段进行组合和反序列化的
eg:
查询的时候没有id字段 在字段里加上就有了
'''
2.使用第三方django—filter实现过滤
安装django-filter
pip3.8 install django-filter -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
'''
注意:django版本会自动升级为最新版本 需要修改回来
'''
再执行一下
pip3.8 install django==2.2.2 -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = []
authentication_classes = []
throttle_classes = []
filter_backends = [DjangoFilterBackend]
filterset_fields = ['name','price']
支持的查询方式(完整查询)
http://127.0.0.1:8000/api/v1/books/?price=939
http://127.0.0.1:8000/api/v1/books/?price=22&name=红楼梦
3.自己定制过滤类实现过滤
查询价格大于100的所有图书
http://127.0.0.1:8000/api/v1/books/?price_gt=100
第一步; 定义一个过滤类,继承BaseFilterBackend,重写filter_queryset方法
from rest_framework.filters import BaseFilterBackend
class CommonFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
price_gt = request.query_params.get('price_gt', None)
if price_gt:
qs = queryset.filter(price__gt=int(price_gt))
return qs
else:
return queryset
第二步:配置在视图类上
from .filter import CommonFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [CommonFilter]
自己定制的类 在视图类下可以添加另外两种过滤方式(SearchFilter,DjangoFilterBackend)的编写 但是要加上过滤的字段
内置过滤类 : search_fields = ['name', 'price']
第三方过滤类:filterset_fields = ['name', 'price']
排序的使用
在过滤的基础上加上排序
from rest_framework.filters import SearchFilter,OrderingFilter
from .filter import CommonFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [CommonFilter,OrderingFilter]
ordering_fields = ['price']
支持的查询方法:
http://127.0.0.1:8000/api/v1/books/?ordering=price
http://127.0.0.1:8000/api/v1/books/?ordering=-price
http://127.0.0.1:8000/api/v1/books/?ordering=-id,price
分页
分页 只有查询所有接口 才有分页 (必须继承GenericAPIView才有分页类)
drf内置了三个分页器,对应三种分页方式
内置的分页类不能直接使用,需要继承 定制一些参数后才能使用
分页使用,自定义一个分页类(三种)
一般用这种
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
class CommonPageNumberPagination(PageNumberPagination):
page_size = 2
page_query_param = 'page'
page_size_query_param = 'size'
max_page_size = 5
class CommonLimitOffsetPagination(LimitOffsetPagination):
default_limit = 3
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5
class CommonCursorPagination(CursorPagination):
cursor_query_param = 'cursor'
page_size = 2
ordering = 'id'
配置在视图类上即可
from .page import CommonPageNumberPagination as PageNumberPagination
from .page import CommonLimitOffsetPagination as LimitOffsetPagination
from .page import CommonCursorPagination
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = []
authentication_classes = []
throttle_classes = []
pagination_class = CommonCursorPagination
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 上周热点回顾(3.3-3.9)