今日内容详细
认证组件
有些接口需要登录才能够访问 有些不需要登录就可以直接访问 由此引出来了认证组件
需求查看所有和创建无需登陆 其他需要登录
先写一个登录接口
class LoginView(ViewSet):
@action(methods=['post'], detail=False)
def login(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(name=username, pwd=password).first()
if user:
token = uuid.uuid4()
UserToken.objects.update_or_create(user=user, defaults={'token': token})
return Response({'code': 100, 'msg': '登陆成功', 'token': token})
return Response({'code': 101, 'msg': '用户名或密码错误'})
@action(methods=['post'], detail=False)
def register(self, request):
username = request.data.get('username')
password = request.data.get('password')
user = User.objects.filter(name=username).first()
if not user:
User.objects.create(name=username, pwd=password)
return Response({'code': 100, 'msg': '注册成功'})
return Response({'code': 101, 'msg': '用户以存在'})
认证组件的使用步骤
1.先写一个认证类 继承BaseAuthentication
2.重写authenticate方法 在该方法内编写认证
3.认证成功返回两个值 [当前登录用户, token]
4.认证不成功抛出异常 AuthenticationFailed
5.可以定义局部使用和全局使用
局部: 直接在视图类中添加属性 authentication_classes = [认证类]
全局: 配置文件中添加
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES':['认证类路径']
}
局部禁用: 在视图类中添加属性 authentication_classes = []
认证类
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import UserToken
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
token = request.META.get('HTTP_TOKEN')
if token:
user = UserToken.objects.filter(token=token).first()
if user:
return user.user, token
raise AuthenticationFailed('token错误')
raise AuthenticationFailed('token没传')
视图类
class BookView(ViewSetMixin, ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookDetailView(ViewSetMixin, RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
路由
from django.urls import path, include
from rest_framework import routers
from app01 import views
router = routers.SimpleRouter()
router.register('books', views.BookView, 'books')
router.register('books', views.BookDetailView, 'books')
router.register('user', views.LoginView, 'user')
urlpatterns = [
path('admin/', admin.site.urls),
path('api/v1/', include(router.urls)),
]
权限组件
即使登陆成功了 有些接口还是无法访问的 如视频网站 即使登陆了还是无法看vip视频 是因为设置了权限 通常权限就是数据库中的一个字段
需求
查询所有和创建登陆用户都可以访问
其他接口需要管理员才可以访问
权限组件使用步骤
1.写一个权限类 继承BasePermission
2.重写has_permission方法 在该方法中实现权限认证 并且在这里request.user就是当前登录用户
3.有权限 返回True
4.没有权限 返回False
5.局部使用和全局使用
局部: 直接在视图类中添加属性 permission_classes = [权限类]
全局: 配置文件中添加
REST_FRAMEWORK = {
'DEFAULT_PERMISSION_CLASSES':['权限类路径']
}
局部禁用: 在视图类中添加属性 permission_classes = []
权限类
from rest_framework.permissions import BasePermission
class CommonPermission(BasePermission):
def has_permission(self, request, view):
if request.user.user_type == 1:
return True
self.message = f'您是{request.user.get_user_type_display()} 没有权限'
return False
视图类
class BookView(ViewSetMixin, ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookDetailView(ViewSetMixin, RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
permission_classes = [CommonPermission]
频率组件
用于控制接口访问的频率
频率组件使用步骤
1.写一个频率类 继承SimpleRateThrottle
2.重写get_cache_key方法 该方法返回啥 就以什么做限制
3.配置一个类属性 scope = '随意起'
4.在配置文件中配置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
'给scope取的名字': '次数/m',
},
}
5.局部使用和全局使用
局部: 直接在视图类中添加属性 throttle_classes = [频率类]
全局: 配置文件中添加
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_CLASSES':['频率类路径']
}
局部禁用: 在视图类中添加属性 throttle_classes = []
频率类
from rest_framework.throttling import SimpleRateThrottle
class CommonThrottle(SimpleRateThrottle):
scope = 'throttle'
def get_cache_key(self, request, view):
return request.META.get('REMOTE_ADDR')
视图类
class BookView(ViewSetMixin, ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
throttle_classes = [CommonThrottle]
class BookDetailView(ViewSetMixin, RetrieveUpdateDestroyAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
permission_classes = [CommonPermission]
throttle_classes = [CommonThrottle]
过滤排序
restful规范中 规定了请求地址中要带过滤条件
所有接口中 只有查询所有接口需要带过滤和排序
需求 查询以红开头的所有图书
方式一:
使用内置的过滤类
from rest_framework.filters import SearchFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [SearchFilter]
search_fields = ['name','price']
查询方式
以url携带参数的形式 且参数名必须得是search
如: http://127.0.0.1:8000/api/v1/books/?search=红
方式二:
使用第三方django-filter实现
pip3.8 install django-filter
from django_filters.rest_framework import DjangoFilterBackend
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend]
filter_fields = ['name','price']
查询方式
以url携带参数的形式 参数名为指定字段名
如: http://127.0.0.1:8000/api/v1/books/?price=939&name=红楼梦
方式三:
自定义过滤类
第一步:定义一个过滤类 继承BaseFilterBackend
第二步:重写filter_queryset方法
第三步:如果携带条件 那么返回对应结果
第四步:没携带 那么返回所有数据
过滤类
class CommonFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
price_gt = request.query_params.get('price_gt')
if price_gt:
qs = queryset.filter(price__gt=price_gt)
return qs
return queryset
视图类
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [CommonFilter]
排序
使用内置的即可
from rest_framework.filters import OrderingFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [OrderingFilter]
ordering_fields = ['price', id]
查询方法
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=-price,id
分页
分页,只有查询所有接口,才有分页
drf内置了三个分页器,对应三种分页方式
内置的分页类不能直接使用,需要继承,定制一些参数后才能使用
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination
'''
page_size 每页数目
page_query_param 前端发送的页数关键字名,默认为”page”
page_size_query_param 前端发送的每页数目关键字名,默认为None
max_page_size 前端最多能设置的每页数量
'''
class CommonPageNumberPagination(PageNumberPagination):
page_size = 2
page_query_param = 'page'
page_size_query_param = 'size'
max_page_size = 5
'''
default_limit 默认限制,默认值与PAGE_SIZE设置一致
limit_query_param limit参数名,默认’limit’
offset_query_param offset参数名,默认’offset’
max_limit 最大limit限制,默认None
'''
class CommonLimitOffsetPagination(LimitOffsetPagination):
default_limit = 2
limit_query_param = 'limit'
offset_query_param = 'offset'
max_limit = 5
'''
cursor_query_param:默认查询字段,不需要修改
page_size:每页数目
ordering:按什么排序,需要指定
'''
class CommonCursorPagination(CursorPagination):
cursor_query_param = 'cursor'
page_size = 2
ordering = 'id'
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
pagination_class = CommonCursorPagination
注意!!!当排序与游标分页一起使用时 需要先排序在分页
如:http://127.0.0.1:8000/api/v1/books/
http://127.0.0.1:8000/api/v1/books/?ordering=price
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· .NET Core 中如何实现缓存的预热?
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性