drf-认证权限频率过滤排序分页
Posted 404 NotFound
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了drf-认证权限频率过滤排序分页相关的知识,希望对你有一定的参考价值。
1.认证组件
1.1 局部认证
1.首先写两个接口,一个查询单个一个查询所有,我们利用视图扩展类和视图子类写在一个视图类上:
views.py:
from rest_framework.viewsets import ViewSetMixin
from rest_framework.generics import ListAPIView
from rest_framework.mixins import RetrieveModelMixin
class BookView(ViewSetMixin,ListAPIView,RetrieveModelMixin):
queryset = Book.objects.all()
serializer_class = BookSerializer
# ViewSetMixin:负责自动生成路由
# ListAPIView:继承扩展类ListModelMixin,里面有list方法
# RetrieveModelMixin:里面有retrieve方法
serializer.py:
from rest_framework import serializers
from .models import Book
class BookSerializer(serializers.ModelSerializer):
class Meta:
model = Book
fields = [\'name\',\'price\',\'publish\',\'authors\',\'publish_detail\',\'author_detail\']
extra_kwargs =
\'name\':\'max_length\':8,
\'price\': \'max_length\': 8,
\'publish_detail\':\'read_only\':True,
\'author_detail\':\'read_only\':True,
\'publish\':\'write_only\':True,
\'authors\':\'write_only\':True
models.py:
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
class UserToken(models.Model):
token = models.CharField(max_length=64)
user = models.OneToOneField(to=\'User\',on_delete=models.CASCADE)
"""
写在两个视图类上按照以下写法:
"""
views.py:
class BookView(ViewSetMixin,ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookDetailView(ViewSetMixin,RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# RetrieveAPIView继承RetrieveModelMixin和GenericAPIView,GenericAPIView中有queryset和serializer_class方法,所以继承RetrieveAPIView不继承RetrieveModelMixin。
models.py、serializer.py和之前一样
2.接下来我们想在查询单个图书接口上加上认证组件:
1.写一个认证类,继承BaseAuthentication
2.重写authenticate方法,拿到请求的数据(GET请求请求体当中不能携带数据,一般选用在请求头和地址栏当中携带数据),用该数据在数据库UserToken表中查找
3.如果认证成功则返回两个值:用户对象和随机字符串token。认证失败则抛出异常AuthenticationFailed。
4.局部使用:
class BookDetailView(ViewSetMixin,RetrieveAPIView): authentication_classes = [LoginAuth]
3.代码:
authenticate.py:
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.query_params.get(\'token\')
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未上传\')
views.py:
class BookDetailView(ViewSetMixin,RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
"""
authentication_classes是在:RetrieveAPIView>>>GenericAPIView>>>APIView中,在APIView中完成了三大认证。
"""
serializer.py和models.py中代码未变
1.2 全局认证
在setting.py中设置:
REST_FRAMEWORK =
\'DEFAULT_AUTHENTICATION_CLASSES\': [\'app01.authenticate.LoginAuth\']
此时我们发现即使是登陆也需要上传uuid字符串,不符合逻辑,需要在登陆类免除登录设置:
views.py:
class UserView(ViewSet):
# 局部解除全局限制
authentication_classes = []
@action(methods=[\'POST\'],detail=False,url_path=\'login\',url_name=\'login\')
def login(self,request):
username = request.data.get(\'username\')
password = request.data.get(\'password\')
user_obj = User.objects.filter(username=username,password=password).first()
if user_obj:
token = str(uuid.uuid4())
UserToken.objects.update_or_create(user=user_obj,defaults=\'token\':token)
return Response(\'code\':100,\'msg\':\'登陆成功\',\'token\':token)
else:
return Response(\'code\':101,\'msg\':\'用户名或密码错误\')
class BookView(ViewSetMixin,ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
class BookDetailView(ViewSetMixin,RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
2.权限组件
2.1 局部权限
1.在某些软件上即使登陆成功,也不能访问,因为没有权限。这是由于在user表中增加了一个字段,用来区分是普通用户还是管理员(会员)。
2.步骤:
1 写一个权限类,继承BasePermission
2 重写has_permission方法,在该方法在中实现权限认证,在这方法中,request.user就是当前登录用户
3 如果有权限,返回True
4 没有权限,返回False,定制返回的中文: self.message=\'中文\'
5 局部使用和全局使用
3.代码:
models.py:
class User(models.Model):
username = models.CharField(max_length=32)
password = models.CharField(max_length=32)
user_type = models.IntegerField(choices=((1,\'超级会员\'),(2,\'普通用户\')),default=2)
permissions.py:
from rest_framework.permissions import BasePermission
class MyPermission(BasePermission):
def has_permission(self, request, view):
if request.user.user_type == 1:
return True
else:
# self.message是定制的中文提示
self.message = \'您是%s,无权访问\' % request.user.get_user_type_display()
# get_字段名_display()可以拿到字段中choice中的注释
return False
views.py:
class BookDetailView(ViewSetMixin,RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
permission_classes = [MyPermission]
2.2 全局权限
如果很多视图类都要执行该权限,可以在设置中设置全局权限,并且可以对指定的视图类免除该权限:
settings.py:
REST_FRAMEWORK =
\'DEFAULT_PERMISSION_CLASSES\': [\'app01.permissions.MyPermission\']
views.py:
class BookDetailView(ViewSetMixin,RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
# 局部禁用
permission_classes = []
permissions.py同上
"""
如果我们用原生的认证和权限,完成该功能:只有登录的用户并且上传token需要配合原生的认证类和权限类使用:
from rest_framework_jwt.authentication import JSONWebTokenAuthentication
from rest_framework.permissions import IsAuthenticated
class CarModelView(ModelViewSet):
queryset = CarMode.objects.all()
serializer_class = CarModelSerializer
authentication_classes = [JSONWebTokenAuthentication] # 校验token有没有传
permission_classes = [IsAuthenticated] # 校验是否登陆
"""
3.频率组件
3.1 局部频率限制
1.方法:
1.写一个频率类,继承SimpleRateThrottle
2.重写get_cache_key方法,返回什么,就以什么做限制(一般以用户ip地址和id做限制)
3.配置一个类属性:scope = \'zkz\'
4.在配置文件中配置:m:每分钟;h:每小时;d:每天
REST_FRAMEWORK =
\'DEFAULT_THROTTLE_RATES\':
\'zkz\': \'3/m\',
2.代码:
throttling.py:
from rest_framework.throttling import SimpleRateThrottle
class MyThrottle(SimpleRateThrottle):
scope = \'zkz\'
def get_cache_key(self, request, view):
# 拿到客户端的ip地址
# print(request.META.get(\'REMOTE_ADDR\')) # 127.0.0.1 本机访问是127.0.0.1
return request.META.get(\'REMOTE_ADDR\')
"""
从地址栏取数据:request.query_params.get(\'token\')
从原生django的cookie中取:request.COOKIE.get(\'sessioned\')
get请求从请求头中取:request.META.get(\'HTTP_TOKEN\')(前端的请求头键是token,经过了包装)
"""
views.py:
class BookDetailView(ViewSetMixin,RetrieveAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
authentication_classes = [LoginAuth]
permission_classes = [MyPermission]
throttle_classes = [MyThrottle]
settings.py:
REST_FRAMEWORK =
\'DEFAULT_THROTTLE_RATES\':
\'zkz\': \'3/m\',
3.2 全局频率限制
settings.py:
REST_FRAMEWORK =
\'DEFAULT_THROTTLE_RATES\':
\'zkz\': \'3/m\',
,
\'DEFAULT_THROTTLE_CLASSES\':
[\'app01.throttling.MyThrottle\'],
视图类中如果不需要频率限制只需要修改:throttle_classes = []
4.过滤
4.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\']
访问的路由要修改成:?search=xxx
eg:?search=三:表示name字段中带有san自的数据对象都可以被筛选出来
"""
search_fields也可以上传多个字段,多个字段内如果都有待匹配的字段,都可以匹配得到:
search_fields=[\'name\',\'price\']
"""
方式二:
利用django-filter模块:可以多个条件同时匹配:
views.py:
from django_filters.rest_framework import DjangoFilterBackend
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [DjangoFilterBackend]
filterset_fields = [\'name\', \'price\']
方式三:利用自定义过滤器:自定义一个py文件:filter.py,在里面编写过去条件,返回值是queryset
filter.py:
from rest_framework.filters import BaseFilterBackend
class MyFilter(BaseFilterBackend):
def filter_queryset(self, request, queryset, view):
# 可以自定义大于或者小于
price = request.query_params.get(\'price__gt\',None)
if price:
return queryset.filter(price__gt=price)
else:
return queryset
views.py:
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [MyFilter] # 可以定制多个,从左往右排
5.排序
from rest_framework.filters import OrderingFilter
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
# 可以先过滤在排序,也可以先排序在过滤,也可以只排序或过滤
filter_backends = [MyFilter,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:降序
"""
也可以按照多个字段排序:
ordering_fields = [\'id\',\'price\']
路由:http://127.0.0.1:8000/api/v1/books/?ordering=price,-id:按照价格升序,按照id降序
"""
6.分页
方式一:自定义一个分页类:
mypage.py:
from rest_framework.pagination import PageNumberPagination
class MyPage(PageNumberPagination):
page_size = 2 # 每页显示2条
page_query_param = \'page\' # page=10:查询第10页的数据
page_size_query_param = \'size\' # page=10&size=5:查询10页每页显示5条
max_page_size = 5 # 每页最大显示条数
views.py:
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
filter_backends = [MyFilter,OrderingFilter]
ordering_fields = [\'id\',\'price\']
# pagination_class只能选一种,所以不能加列表
pagination_class = MyPage
方式二:
LimitOffset
class CommonLimitOffsetPagination(LimitOffsetPagination):
default_limit = 3 # 每页显示2条
limit_query_param = \'limit\' # limit=3 取3条
offset_query_param = \'offset\' # offset=1 从第一个位置开始,取limit条
max_limit = 5
# offset=3&limit=2 0 1 2 3 4 5
方式三:
class CommonCursorPagination(CursorPagination):
cursor_query_param = \'cursor\' # 查询参数
page_size = 2 # 每页多少条
ordering = \'id\' # 排序字段
# 配置在视图类上即可
class BookView(ViewSetMixin, ListAPIView):
queryset = Book.objects.all()
serializer_class = BookSerializer
permission_classes = []
authentication_classes = []
throttle_classes = []
# 之前的东西一样用 ,内置的分页类不能直接使用,需要继承,定制一些参数后才能使用
# pagination_class = PageNumberPagination
#基本分页方式(基本是这种,网页端):http://127.0.0.1:8000/api/v1/books/?page=2&size=3
# pagination_class = LimitOffsetPagination
# 偏移分页 http://127.0.0.1:8000/api/v1/books/?limit=4&offset=1
# 从第一条开始,取4条
pagination_class = CommonCursorPagination
# 游标分页,只能下一页,上一页,不能跳到中间,但它的效率最高,大数据量分页,使用这种较好
DRF框架——drf-jwt手动签发与校验过滤组件筛选组件排序组件分页组件
自定义drf-jwt手动签发和校验
签发token源码入口
前提:给一个局部禁用了所有 认证与权限 的视图类发送用户信息得到token,其实就是登录接口,不然进不了登录页面
获取提交的username和password 1)rest_framework_jwt.views.ObtainJSONWebToken 的 父类 JSONWebTokenAPIView 的 post 方法 接受有username、password的post请求
校验数据,并且签发token 2)post方法将请求数据交给 rest_framework_jwt.serializer.JSONWebTokenSerializer 处理 完成数据的校验,会走序列化类的 全局钩子校验规则,校验得到登录用户并签发token存储在序列化对象中
核心源码:rest_framework_jwt.serializer.JSONWebTokenSerializer的validate(self,attrs)方法
def validate(self, attrs): # 账号密码字典 credentials = { self.username_field: attrs.get(self.username_field), ‘password‘: attrs.get(‘password‘) } if all(credentials.values()): # 签发token第1步:用账号密码得到user对象 user = authenticate(**credentials) if user: if not user.is_active: msg = _(‘User account is disabled.‘) raise serializers.ValidationError(msg) # 签发token第2步:通过user得到payload,payload包含着用户信息与过期时间 payload = jwt_payload_handler(user) # 在视图类中,可以通过 序列化对象.object.get(‘user‘或者‘token‘) 拿到user和token return { # 签发token第3步:通过payload签发出token ‘token‘: jwt_encode_handler(payload), ‘user‘: user } else: msg = _(‘Unable to log in with provided credentials.‘) raise serializers.ValidationError(msg) else: msg = _(‘Must include "{username_field}" and "password".‘) msg = msg.format(username_field=self.username_field) raise serializers.ValidationError(msg)
手动签发token逻辑 (主要就是jwt_payload_handler和jwt_encode_handler这两个方法,在源码settings中生成token)
1)通过username、password得到user对象 2)通过user对象生成payload:jwt_payload_handler(user) => payload from rest_framework_jwt.serializers import jwt_payload_handler 3)通过payload签发token:jwt_encode_handler(payload) => token from rest_framework_jwt.serializers import jwt_encode_handler
签发token总结
jwt_payload_handler方法传入登录对象,返回payload(包含用户信息,过期时间) jwt_encode_handler方法传入payload,返回一个加密的token 流程:获取登录用户对象user--->jwt_payload_handler(user)生成payload(包含用户信息和过期时间)--->jwt_encode_handler(payload)生成一个加密的token
校验token源码入口
前提:访问一个配置了jwt认证规则的视图类,就需要提交认证字符串token,在认证类中完成token的校验 1)rest_framework_jwt.authentication.JSONWebTokenAuthentication 的 父类 BaseJSONWebTokenAuthentication 的 authenticate 方法 请求头拿认证信息jwt-token => 通过反爬小规则确定有用的token => payload => user
核心源码: rest_framework_jwt.authentication.BaseJSONWebTokenAuthentication的authenticate(self,request)方法
def authenticate(self, request): """ Returns a two-tuple of `User` and token if a valid signature has been supplied using JWT-based authentication. Otherwise returns `None`. """ # 带有反爬小规则的获取token:前台必须按 "jwt token字符串" 方式提交 # 校验user第1步:从请求头 HTTP_AUTHORIZATION 中拿token,并提取 jwt_value = self.get_jwt_value(request) # 游客 if jwt_value is None: return None # 校验 try: # 校验user第2步:token => payload payload = jwt_decode_handler(jwt_value) except jwt.ExpiredSignature: msg = _(‘Signature has expired.‘) raise exceptions.AuthenticationFailed(msg) except jwt.DecodeError: msg = _(‘Error decoding signature.‘) raise exceptions.AuthenticationFailed(msg) except jwt.InvalidTokenError: raise exceptions.AuthenticationFailed() # 校验user第3步:payload => user user = self.authenticate_credentials(payload) return (user, jwt_value)
手动校验token逻辑
1)从请求头中获取token 2)根据token解析出payload:jwt_decode_handler(token) => payloay from rest_framework_jwt.authentication import jwt_decode_handler 3)根据payload解析出user:self.authenticate_credentials(payload) => user 继承drf-jwt的BaseJSONWebTokenAuthentication,拿到父级的authenticate_credentials方法
校验token总结
从请求头中获取token--->jwt_decode_handler(token)获取到payloay--->self.authenticate_credentials(payload)获取到user
案例:实现多方式登录签发token
models.py
from django.db import models from django.contrib.auth.models import AbstractUser class User(AbstractUser): mobile = models.CharField(max_length=11, unique=True) class Meta: db_table = ‘api_user‘ verbose_name = ‘用户表‘ verbose_name_plural = verbose_name def __str__(self): return self.username
serializers.py 生成token
#生成token的两个函数 user=>payload=>token from rest_framework_jwt.serializers import jwt_payload_handler from rest_framework_jwt.serializers import jwt_encode_handler from rest_framework import serializers from . import models import re # 1) 前台提交多种登录信息都采用一个key,所以后台可以自定义反序列化字段进行对应 # 2) 序列化类要处理序列化与反序列化,要在fields中设置model绑定的Model类所有使用到的字段 # 3) 区分序列化字段与反序列化字段 read_only | write_only # 4) 在自定义校验规则中(局部钩子、全局钩子)校验数据是否合法、确定登录的用户、根据用户签发token # 5) 将登录的用户与签发的token保存在序列化类对象中 #前台有两个输入框:一个账号框(可以填用户名、手机号、邮箱)usr,一个密码框 pwd class UserModelSerializer(serializers.ModelSerializer): # 自定义反序列字段:一定要设置write_only,只参与反序列化,不会与model类字段映射 usr = serializers.CharField(write_only=True) pwd = serializers.CharField(write_only=True) class Meta: model=models.User fields = [‘usr‘, ‘pwd‘, ‘username‘, ‘mobile‘, ‘email‘] # 系统校验规则和前面write_only设计方式一样 extra_kwargs = { ‘username‘: { ‘read_only‘: True }, ‘mobile‘: { ‘read_only‘: True }, ‘email‘: { ‘read_only‘: True }, } #全局钩子,校验数据 def validate(self, attrs): usr = attrs.get(‘usr‘) pwd = attrs.get(‘pwd‘) # 多方式登录:各分支处理得到该方式下对应的用户 if re.match(r‘.+@.+‘, usr): #判断是否是邮箱登录 user_query = models.User.objects.filter(email=usr) elif re.match(r‘1[3-9][0-9]{9}‘, usr): #判断是否是手机号登录 user_query = models.User.objects.filter(mobile=usr) else: #用户名登录 user_query = models.User.objects.filter(username=usr) user_obj = user_query.first() # 签发token:得到登录用户,签发token并存储在实例化对象中 if user_obj and user_obj.check_password(pwd): # 签发token,将token存放到 实例化类对象的token 名字中 pyload = jwt_payload_handler(user_obj) token = jwt_encode_handler(pyload) # 将当前用户与签发的token都保存在序列化对象中 self.user = user_obj self.token = token return attrs raise serializers.ValidationError({‘data‘: ‘数据有误‘})
结果只显示fields中的read_only字段
视图层:views.py
#实现多方式登陆签发token:账号、手机号、邮箱等登陆 # 1) 禁用认证与权限组件 # 2) 拿到前台登录信息,交给序列化类 # 3) 序列化类校验得到登录用户与token存放在序列化对象中 # 4) 取出登录用户与token返回给前台 import re from . import serializers, models from utils.response import APIResponse from rest_framework.views import APIView from rest_framework_jwt.serializers import jwt_payload_handler from rest_framework_jwt.serializers import jwt_encode_handler class LoginAPIView(APIView): # 1) 禁用认证与权限组件 authentication_classes = [] permission_classes = [] def post(self, request, *args, **kwargs): # 2) 拿到前台登录信息,交给序列化类,规则:账号用usr传,密码用pwd传 user_ser = serializers.UserModelSerializer(data=request.data) # 3) 序列化类校验得到登录用户与token存放在序列化对象中 user_ser.is_valid(raise_exception=True) # 4) 取出登录用户与token返回给前台 return APIResponse(token=user_ser.token, results=serializers.UserModelSerializer(user_ser.user).data)
# "一根筋" 思考方式:所有逻辑都在视图类中处理 def my_post(self, request, *args, **kwargs): usr = request.data.get(‘usr‘) pwd = request.data.get(‘pwd‘) if re.match(r‘.+@.+‘, usr): user_query = models.User.objects.filter(email=usr) elif re.match(r‘1[3-9][0-9]{9}‘, usr): user_query = models.User.objects.filter(mobile=usr) else: user_query = models.User.objects.filter(username=usr) user_obj = user_query.first() if user_obj and user_obj.check_password(pwd): payload = jwt_payload_handler(user_obj) token = jwt_encode_handler(payload) return APIResponse(results={‘username‘: user_obj.username}, token=token) return APIResponse(data_msg=‘不可控错误‘)
使用Postman,post请求,json格式传参 usr和pwd,返回用户信息和token值
案例:自定义认证反爬规则校验token
authentications.py
import jwt from rest_framework_jwt.authentication import BaseJSONWebTokenAuthentication from rest_framework_jwt.authentication import jwt_decode_handler from rest_framework.exceptions import AuthenticationFailed class JWTAuthentication(BaseJSONWebTokenAuthentication): def authenticate(self, request): #从前端取出token值,放在HTTP_AUTHORIZATION中 jwt_token = request.META.get(‘HTTP_AUTHORIZATION‘) # 自定义校验规则:auth token jwt token = self.parse_jwt_token(jwt_token) if token is None: return None try: # token => payload payload = jwt_decode_handler(token) except jwt.ExpiredSignature: raise AuthenticationFailed(‘token已过期‘) except: raise AuthenticationFailed(‘非法用户‘) # payload => user user = self.authenticate_credentials(payload) return (user, token) #获取到登录对象和签发的token # 自定义校验规则:auth token jwt,auth为前盐,jwt为后盐 def parse_jwt_token(self, jwt_token): tokens = jwt_token.split() if len(tokens) != 3 or tokens[0].lower() != ‘auth‘ or tokens[2].lower() != ‘jwt‘: return None return tokens[1]
views.py
from rest_framework.views import APIView from utils.response import APIResponse # 必须登录后才能访问 - 通过了认证权限组件 from rest_framework.permissions import IsAuthenticated # 自定义jwt校验规则 from .authentications import JWTAuthentication class UserDetail(APIView): authentication_classes = [JWTAuthentication] #返回user对象和token permission_classes = [IsAuthenticated] def get(self, request, *args, **kwargs): return APIResponse(results={‘username‘: request.user.username})
群查接口各种筛选组件数据准备
models.py
class Car(models.Model): name = models.CharField(max_length=16, unique=True, verbose_name=‘车名‘) price = models.DecimalField(max_digits=10, decimal_places=2, verbose_name=‘价格‘) brand = models.CharField(max_length=16, verbose_name=‘品牌‘) class Meta: db_table = ‘api_car‘ verbose_name = ‘汽车表‘ verbose_name_plural = verbose_name def __str__(self): return self.name
admin.py
admin.site.register(models.Car)
serializers.py
class CarModelSerializer(serializers.ModelSerializer): class Meta: model = models.Car fields = [‘name‘, ‘price‘, ‘brand‘]
views.py
# Car的群查接口 from rest_framework.generics import ListAPIView class CarListAPIView(ListAPIView): queryset = models.Car.objects.all() serializer_class = serializers.CarModelSerializer
urls.py
url(r‘^cars/$‘, views.CarListAPIView.as_view()),
drf搜索过滤组件
views.py
from rest_framework.generics import ListAPIView # 第一步:drf的SearchFilter - 搜索过滤 from rest_framework.filters import SearchFilter class CarListAPIView(ListAPIView): queryset = models.Car.objects.all() serializer_class = serializers.CarModelSerializer # 第二步:局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS) filter_backends = [SearchFilter] # 第三步:SearchFilter过滤类依赖的过滤条件 => 接口:/cars/?search=... search_fields = [‘name‘, ‘price‘] #筛选字段 # eg:/cars/?search=1,name和price中包含1的数据都会被查询出
drf排序过滤组件
views.py
from rest_framework.generics import ListAPIView # 第一步:drf的OrderingFilter - 排序过滤 from rest_framework.filters import OrderingFilter class CarListAPIView(ListAPIView): queryset = models.Car.objects.all() serializer_class = serializers.CarModelSerializer # 第二步:局部配置 过滤类 们(全局配置用DEFAULT_FILTER_BACKENDS) filter_backends = [OrderingFilter] # 第三步:OrderingFilter过滤类依赖的过滤条件 => 接口:/cars/?ordering=... ordering_fields = [‘pk‘, ‘price‘] # eg:/cars/?ordering=-price,pk,先按price降序,如果出现price相同,再按pk升序
drf基础分页组件
paginations.py
from rest_framework.pagination import PageNumberPagination class MyPageNumberPagination(PageNumberPagination): # ?page=页码 page_query_param = ‘page‘ # ?page=页面 下默认一页显示的条数 page_size = 3 # ?page=页面&page_size=条数 用户自定义一页显示的条数 page_size_query_param = ‘page_size‘ # 用户自定义一页显示的条数最大限制:数值超过5也只显示5条 max_page_size = 5
views.py
from rest_framework.generics import ListAPIView class CarListAPIView(ListAPIView): # 如果queryset没有过滤条件,就必须 .all(),不然分页会出问题 queryset = models.Car.objects.all() serializer_class = serializers.CarModelSerializer # 分页组件 - 给视图类配置分页类即可 - 分页类需要自定义,继承drf提供的分页类即可 pagination_class = pagenations.MyPageNumberPagination
以上是关于drf-认证权限频率过滤排序分页的主要内容,如果未能解决你的问题,请参考以下文章
自定义类签发校验token-实现多方式登录-自定义反爬类-admin后台表管理字段自定义-群查接口-搜索-排序-分页