当前位置:网站首页>drf路由组件Routers
drf路由组件Routers
2022-08-02 14:01:00 【意大利面拌42号混凝土】
drf路由组件Routers
对于视图集ViewSet,我们除了可以自己手动指明请求方式与动作action之间的对应关系外,还可以使用Routers来帮助我们快速实现路由信息。
REST framework提供了两个router
- SimpleRouter
- DefaultRouter
一、使用方法
创建Router对象,并注册视图集
# 导入SimpleRouter与DafaultRouter包
from rest_farmework.routers import SimpleRouter,DafaultRouter
# 实例化对象
simplerouter = SimpleRouter()
defaultrouter = DafaultRouter()
# 路由注册
simplerouter.register('login/',StudentModelViewSet,basename='login')
register(prefix, viewset, base_name)
- prefix 该视图集的路由前缀
- viewset 视图集
- base_name 路由别名的前缀
如上述代码会形成的路由如下:
^books/$ name: book-list
^books/{
pk}/$ name: book-detail
二、添加路由的两种方式
有两种添加方式
第一种
urlpatterns = [
……
]
urlpatterns+=simplerouter.urls
第二种
urlpatterns = [
path('',include(simplerouter.urls))
]
代码演示
# 必须是继承ModelViewSet的视图类才能自动生成路由
from rest_framework.viewsets import ModelViewSet,ReadOnlyModelViewSet
class StudentModelViewSet(ModelViewSet):
queryset = Student.objects.all()
serializer_class = StudentModelSerializer
# 这种方法不会自动生成,需要用action配置
def login(self,request):
"""学生登录功能"""
print(self.action)
return Response({
"message":"登录成功"})
路由代码
from django.urls import path, re_path
from . import views
urlpatterns = [
...
]
"""使用drf提供路由类router给视图集生成路由列表"""
# 实例化路由类
# drf提供一共提供了两个路由类给我们使用,他们用法一致,功能几乎一样
from rest_framework.routers import DefaultRouter
router = DefaultRouter()
# 注册视图集
# router.register("路由前缀",视图集类)
router.register("router_stu",views.StudentModelViewSet)
# 把生成的路由列表追加到urlpatterns
print( router.urls )
urlpatterns += router.urls
上面的代码就成功生成了路由地址[增/删/改/查一条/查多条的功能],但是不会自动我们在视图集自定义方法的路由。
所以我们如果也要给自定义方法生成路由,则需要进行action动作的声明。
1、自动生成路由的视图类
-需要继承ViewSetMixin+9个视图子类
-需要继承ViewSetMixin+视图类+五个视图扩展类
三、视图集中附加action的声明
在视图集中,如果想要让Router自动帮助我们为自定义的动作生成路由信息,需要使用rest_framework.decorators.action装饰器。
以action装饰器装饰的方法名会作为action动作名,与list、retrieve等同。
action装饰器可以接收两个参数:
methods: 声明该action对应的请求方式,列表传递
detail: 声明该action的路径是否与单一资源对应,及是否是
访问的路径,可以不写,如果不写,以方法名作为路径 通过get请求访问这个路径test/login就能触发login的执行
url_path:访问的路径可以不写,,如果不写就会以方法名作为路径,通过get请求访问这个路径test/login就能触发函数login的执行
url_name:别名
# @action(methods=['GET'],detail=False,url_path='login',url_name='login')
@action(methods=['GET'],detail=True)
def login(self, request,pk):
print(self.action)
print(pk)
# self.get_serializer()
return Response('登录成功')
四、drf认证功能Authentication
1、自定义认证类
需要单独新建一个py文件,编写认证类
#自定义认证类,要继承BaseAuthentication,重写authenticate,如果认证通过,返回两个值,如果认证失败,抛认证失败的异常
from rest_framework.authentication import BaseAuthentication
from rest_framework.exceptions import AuthenticationFailed
from .models import UserToken
class LoginAuth(BaseAuthentication):
def authenticate(self, request):
# 校验用户是否登录:看它有没有带token来,以及token是不是合法的(是不是我给的)
token = request.GET.get('token')
# 校验token是否合法(根据token去库中查询是否存在,如果存在,就是登陆了,放行)
user_token = UserToken.objects.filter(token=token).first()
if user_token:
# 带的token是有效的
# user_token.user当前登录用户
return user_token.user, token
else:
raise AuthenticationFailed('token不合法或没有迭代token')
认证类的使用
#局部配置
from app01.auth import LoginAuth
class PublishView(ModelViewSet):
authentication_classes = [LoginAuth,]
# 全局配置
REST_FRAMEWORK={
"DEFAULT_AUTHENTICATION_CLASSES":["app01.auth.LoginAuth",]
}
认证失败会有两种可能的返回值:
- 401 Unauthorized 未认证
- 403 Permission Denied 权限被禁止
2、内置认证类(需要配合权限使用)
可以在配置文件中配置全局默认的认证方案
REST_FRAMEWORK = {
'DEFAULT_AUTHENTICATION_CLASSES': (
'rest_framework.authentication.SessionAuthentication', # session认证
'rest_framework.authentication.BasicAuthentication', # 基本认证
)
}
也可以在每个视图中通过局部设置authentication_classess属性来设置
from rest_framework.authentication import SessionAuthentication, BasicAuthentication
from rest_framework.views import APIView
class ExampleView(APIView):
# 类属性
authentication_classes = [SessionAuthentication, BasicAuthentication]
...
五、drf权限功能Permissions
1、自定义权限类
权限控制可以限制用户对于视图的访问和对于具体数据对象的访问。
- 在执行视图的dispatch()方法前,会先进行视图访问权限的判断
- 在通过get_object()获取具体对象时,会进行模型对象访问权限的判断
编写权限类
# 继承BasePermission,重写has_permission,如果有权限,就返回True,没有权限就返回False
from rest_framework.permissions import BasePermission
class PermissionUser(BasePermission):
def has_permission(self, request, view):
# 如果有权限,返回True
if request.user.user_type == 1:
return True # 超级用户允许访问
else:
return False
权限类使用
#认证类的局部配置
from app01.auth import LoginAuth
class PublishView(ModelViewSet):
# 权限类:publish的5个接口,必须超级用户才能访问
permission_classes = [PermissionUser]
#全局使用
REST_FRAMEWORK={
"DEFAULT_PERMISSION_CLASSES":["app01.auth.PermissionUser",]
}
如需自定义权限,需继承rest_framework.permissions.BasePermission父类,并实现以下两个任何一个方法或全部
- `.has_permission(self, request, view)`
是否可以访问视图, view表示当前视图对象
- `.has_object_permission(self, request, view, obj)`
是否可以访问数据对象, view表示当前视图, obj为数据对象
2、内置权限类
from rest_framework.permissions import AllowAny,IsAuthenticated,IsAdminUser,IsAuthenticatedOrReadOnly
- AllowAny 允许所有用户
- IsAuthenticated 仅通过认证的用户
- IsAdminUser 仅管理员用户
- IsAuthenticatedOrReadOnly 已经登陆认证的用户可以对数据进行增删改操作,没有登陆认证的只能查看数据。
全局使用
REST_FRAMEWORK = {
....
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.IsAuthenticated',
)
}
- 如未指名,则采用如下配置
'DEFAULT_PERMISSION_CLASSES': (
'rest_framework.permissions.AllowAny',
)
局部使用在具体的视图中通过permission_classes属性来设置
from rest_framework.permissions import IsAuthenticated
from rest_framework.views import APIView
class ExampleView(APIView):
permission_classes = [IsAuthenticated,]
...
六、drf频率功能Throttling
1、自定义频率类
2、内置频率类
新建一个名为throttlings.py的文件,名字可以随便取,在里面写限流类
# 使用内置限流类SimpleRateThrottle
from rest_framework.throttling import SimpleRateThrottle
class MyThrottling(SimpleRateThrottle):
# 类中书写一个属性
scope = 'frequency'
# 重写get_cache_key()方法
def get_cache_key(self, request, view):
#返回什么就以什么做限制,此处返回其父类中的get_ident()方法,get_ident()方法为其内置ip限流方法
return self.get_ident(request)
使用方法
# 局部配置
from .serializers import Bookserializers
from .models import Book
from rest_framework.generics import ListCreateAPIView
# 导入自定义编写的限流py文件
from .throttlings import MyThrottling
class BookGenericViewSet(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = Bookserializers
# 使用throttle_classes类属性
""" throttle_classes类属性在类APIView中 """
throttle_classes = [MyThrottling,]
# 全局配置
REST_FRAMEWORK = {
'DEFAULT_THROTTLE_RATES': {
# key值是频率类中scop字段对应的值,value是访问次数限制
'frequency': '3/m',
}
}
七、drf过滤排序功能
首先要明确一点,过滤条件应是在请求地址中
过滤功能有三种,内置过滤功能,第三方的过滤功能和自定义过滤功能
1、内置过滤功能
rest-framework的filters模块有三个类BaseFilterBackend(基类),SearchFilter(过滤查询类),OrderingFilter(排序类)
# 直接导入内置过滤模块,并配置过滤类即可使用
from .serializers import Bookserializers
from .models import Book
from rest_framework.generics import ListCreateAPIView
from rest_framework.filters import SearchFilter
class BookGenericViewSet(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = Bookserializers
# 配置过滤类
filter_backends = [SearchFilter,]
# 配置过滤字段
search_fields=['name'] # url:http://127.0.0.1:8000/book/?search=记
# 也可以配置多重字段,多种条件一起过滤
search_fields=['name','price'] # url:http://127.0.0.1:8000/book/?search=记&search=56
2、内置排序功能
# 直接导入内置过滤模块,并配置排序类类即可使用
from .serializers import Bookserializers
from .models import Book
from rest_framework.generics import ListCreateAPIView
from rest_framework.filters import OrderingFilter
class BookGenericViewSet(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = Bookserializers
# 配置排序类
filter_backends = [OrderingFilter,]
# 配置排序字段
# search_fields=['name']
ordering_fields=['price'] # http://127.0.0.1:8000/book/?ordering=price (按价格的正序排列)
ordering_fields = ['price','id'] # http://127.0.0.1:8000/book/?ordering=price,-id (价格一样,按照id的倒叙排列)
3、过滤排序组合使用
# 过滤排序组合使用
from .serializers import Bookserializers
from .models import Book
from rest_framework.generics import ListCreateAPIView
from rest_framework.filters import SearchFilter,OrderingFilter
class BookGenericViewSet(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = Bookserializers
# 配置过滤与排序类
filter_backends = [SearchFilter,OrderingFilter]
# 配置过滤字段
search_fields = ['name']
# 配置排序字段
ordering_fields = ['price'] # url:http://127.0.0.1:8000/book/?search=记&ordering=-price
4、第三方过滤类的使用
现在我们有这么个需求,我想要价格为56且名字等于西游记的具体数据,怎么办?
http://127.0.0.1:8000/book/?search=西游记&price=56,就现有学习的内容无法实现此功能,这就需要借助于第三方的模块
pip install django-filter
from django_filters.rest_framework import DjangoFilterBackend
# 第三方过滤类的使用
from .serializers import Bookserializers
from .models import Book
from rest_framework.generics import ListCreateAPIView
from django_filters.rest_framework import DjangoFilterBackend
class BookGenericViewSet(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = Bookserializers
# 配置过滤字段
filter_backends = [DjangoFilterBackend]
filter_fields = ['name','price'] # url: http://127.0.0.1:8000/book/?name=西游记&price=56
1、自定义过滤类
新建一个过滤FilterBackend.py文件
# 自定义过滤类
from rest_framework.filters import BaseFilterBackend
class MyFilterBackend(BaseFilterBackend):
# url: http://127.0.0.1:8000/book/?price__gt=56
def filter_queryset(self, request, queryset, view):
# queryset就是要过滤的数据
price= request.query_params.get('price__gt')
if price:
queryset = queryset.filter(price__gt=price)
return queryset
view.py
# 自定义过滤类的使用
from .serializers import Bookserializers
from .models import Book
from rest_framework.generics import ListCreateAPIView
from .FilterBackend import MyFilterBackend
class BookGenericViewSet(ListCreateAPIView):
queryset = Book.objects.all()
serializer_class = Bookserializers
filter_backends = [MyFilterBackend]
八、drf分页功能
############## 自定义分页类
##基本分页
from rest_framework.pagination import PageNumberPagination,LimitOffsetPagination,CursorPagination
##基本分页
class MyPageNumberPagination(PageNumberPagination):
# 重写4个类属性即可
page_size = 2 # 每页显示两条
page_query_param = 'page' # 查询条件 http://127.0.0.1:8000/books/?page=2
page_size_query_param = 'size' # http://127.0.0.1:8000/books/?page=2&size=4 获取第二页数据,返回4条
max_page_size = 5 # http://127.0.0.1:8000/books/?page=2&size=400 获取第二页数据,最多返回5条
# 偏移分页
class MyLimitOffsetPagination(LimitOffsetPagination):
# 4个类属性
default_limit = 2 #每页默认显示多少条
limit_query_param = 'limit' # http://127.0.0.1:8000/books/?limit=3
offset_query_param = 'offset'# http://127.0.0.1:8000/books/?limit=3&offset=1 # 从2位置取3条数据
max_limit = 5 # 限制limit最大条数
# 游标分页
class MyCursorPagination(CursorPagination):
cursor_query_param = 'cursor' # 查询条件,无用
page_size = 2 # 每页显示多少条
ordering = 'id' #按谁排序
边栏推荐
猜你喜欢

乐心湖‘s Blog——MySQL入门到精通 —— 囊括 MySQL 入门 以及 SQL 语句优化 —— 索引原理 —— 性能分析 —— 存储引擎特点以及选择 —— 面试题

Mysql's case the when you how to use

Break the limit of file locks and use storage power to help enterprises grow new momentum

Raft协议图解,缺陷以及优化

ZABBIX配置邮件报警和微信报警

You can't accept 60% slump, there is no eligible for gain of 6000% in 2021-05-27

Some impressions of the 519 plummet 2021-05-21

你接受不了60%的暴跌,就没有资格获得6000%的涨幅 2021-05-27

Data Organization---Chapter 6 Diagram---Graph Traversal---Multiple Choice Questions

政策利空对行情没有长期影响,牛市仍将继续 2021-05-19
随机推荐
FreeBSD bnxt以太网驱动源码阅读记录三:
Sentinel源码(二)入口方法分析
Minio文件上传
二极管及其应用
ping命令的使用及代码_通过命令查看ping路径
C# 编译错误:Compiler Error CS1044
replay视频播放器_怎么让手机音乐跟视频一起放
软件测试和硬件测试的区别及概念
关于C#使用DateTime数据的细节
php开源的客服系统_在线客服源码php
Word | 关于删除分节符(下一页)前面的版式就乱了解决方案
史上最全!47个“数字化转型”常见术语合集,看完秒懂~
泡利不相容原理适用的空间范围(系统)是多大?
面试SQL语句,学会这些就够了!!!
保姆级教程:写出自己的移动应用和小程序(篇三)
Awesome!Alibaba interview reference guide (Songshan version) open source sharing, programmer interview must brush
定了!就在7月30日!
网络安全第六次作业
标量替换、栈上分配、同步消除
Sentinel源码(五)FlowSlot以及限流控制器源码分析