drf-day9
过滤
只针对查询所有接口
前提:必须继承 GenericAPIView及其子类
使用方式
方式一:使用drf内置的
查询方式:http://127.0.0.1:8000/books/?search=29 #模糊匹配: 只要名字中有29或价格中有29都能搜出来 from rest_framework.filters import SearchFilter filter_backends = [SearchFilter, OrderingFilter] search_fields = ['name', 'price']
方式二:第三方模块
安装:
pip install django==3.2.12
pip install django-filter
from django_filters.rest_framework import DjangoFilterBackend
http://127.0.0.1:8000/books/?name=红楼梦 http://127.0.0.1:8000/books/?price=19&name=西游记 filter_backends = [DjangoFilterBackend] filterset_fields=['name','price']
方式三:自定义
http://127.0.0.1:8000/books/?price=19&name=书 filter_backends = [MyFilter] # 我自己知道按哪些字段过滤 from rest_framework.filters import BaseFilterBackend from django.db.models import Q class MyFilter(BaseFilterBackend): def filter_queryset(self, request, queryset, view): # 基于queryset 进行过滤,过滤后返回即可 # http://127.0.0.1:8000/books/?name=书 # 名字中有书的就查出来 search_param = request.query_params.get('name') price = request.query_params.get('price') if search_param and price: # queryset = queryset.filter(Q(name__contains=search_param) | Q(price=price)) # qs对象的filter queryset = queryset.filter(name__contains=search_param,price=price) # qs对象的filter return queryset
#### 继承APIView 写过滤,写排序 class BookView(ViewSetMixin, APIView): def list(self, request, *args, **kwargs): # 按名字过滤 print('asfdasdf') name = request.query_params.get('name') book_list = Book.objects.all().filter(name__contains=name) ser = BookSerializer(instance=book_list, many=True) return Response(ser.data
写多个,他们是从左往右,依次执行
大原则,配置多个过滤类的时候,第一个放尽量多个过滤掉数据
配置多个:执行原理
先执行第一个过滤类的:filter_queryset返回qs对象
再执行第二个过滤类的filter_queryset,传入上一个返回的qs,过滤完返回qs对象
分页
只针对于 查询所有接口
分页形式:
web : 下一页,下一页
小程序,app:上拉加载更多
前提:必须继承 GenericAPIView 及其子类
使用方式
方式一:
第一步:创建一个page.py文件,写一个继承PageNumberPagination
from rest_framework.pagination import PageNumberPagination class CommonPageNumberPagination(PageNumberPagination):
第二步:定义四个属性
page_size,每页显示多少条 page_query_param=‘page’指定第几页的key 值 page=4 page_size_query_param = 'size' # 可以指定每页显示多少条 size=300000 max_page_size = 5 # 每页最多显示5条
第三步:在视图类中配置
pagination_class =CommonCursorPagination # 分页方式只有一种,配置一个类即可
方式二:
第一步:创建一个page.py文件,写一个继承LimitOffsetPagination
from rest_framework.pagination import LimitOffsetPagination class CommonLimitOffsetPagination(LimitOffsetPagination):
第二步:定义四个属性
# http://api.example.org/accounts/?limit=4 # 从开始取4条 # http://api.example.org/accounts/?offset=4&limit=5 从第4条开始,取5条 default_limit=2:默认显示几条 limit_query_param = 'limit' # 每页显示多少条的查询条件 offset_query_param = 'offset' # 从第几条开始取数据 max_limit=5limit:最多取5条
第三步:在视图内种配置即可
pagination_class =CommonLimitOffsetPagination# 分页方式只有一种,配置一个类即可
方式三:
第一步:创建一个page.py文件,写一个继承CursorPagination
from rest_framework.pagination import CursorPagination class CommonCursorPagination(CursorPagination):
第二步:
# app上用这个多 # 只能上一页和下一页,不能指定跳转到中间的某页》》》效率高,大数据量用它、 cursor_query_param = 'cursor' # 查询条件,用不到,需要有 page_size = 2 # 每页显示两条 ordering = 'id' # 按id排序 这个必须是表中字段
第三步:在视图中配置即可
pagination_class =CommonCursorPagination# 分页方式只有一种,配置一个类即可
视图类:必须继承
from .page import CommonPageNumberPagination,CommonLimitOffsetPagination,CommonCursorPagination class BookView(ViewSetMixin, ListAPIView): authentication_classes=[] queryset = Book.objects.all() serializer_class = BookSerializer pagination_class =CommonCursorPagination # 分页方式只有一种,配置一个类即可
继承APIView也要实现
class BookView(ViewSet):
def list(self, request, *args, **kwargs):
# # 查询出所有数据
# book_list = Book.objects.all()
# # 实例化分页类
# # 方式一
# # pagination = CommonPageNumberPagination()
# # 方式二
# # pagination = CommonLimitOffsetPagination()
# # 方式三
# pagination = CommonCursorPagination()
# # 对象调用paginate_queryset
# page = pagination.paginate_queryset(book_list, request)
# if page is not None:
# serializer = BookSerializer(page, many=True) # 序列化分页后的数据
# return pagination.get_paginated_response(serializer.data)
异常处理
三大认证 、视图类的方法中执行出错,都会被全局异常捕获
认证类,认证不通过,抛异常,前端看到没有问题,只是返回了提示信息》》》处理了drf的异常
drf全局异常处理,他会把drf的异常处理掉,统一返回格式,但是django原生的和python的都不会处理
无论什么异常都返回固定格式
第一步:创建一个py文件,定义一个函数
def common_exception(exc, context):
第二步:执行一下原来的exception_handler》》》它能处理drf的异常
res = exception_handler(exc, context)
第三步:判断drf是否有异常,有异常就抛drf异常,没有就我们自己处理
if not res: # 有值,说明是drf异常,它处理完了,没有值,是其他异常,我们自己处理 return Response({'code': 999, 'msg': '非drf错误,错误信息是:%s' % str(exc)}) else: return Response({'code': 888, 'msg': 'drf错误,错误信息是:' + res.data.get('detail')})
第四步:在配置文件中配置
REST_FRAMEWORK = {
'EXCEPTION_HANDLER': 'app01.exceptions.common_exception', # 以后只要出了异常,都会走这个函数
补充
1、DateField、DateTimeField
auto_now_add=True # 创建数据时自动添加当前时间 auto_now=True # 每次操作数据时更新为当前时间
2 session认证的原理
写一个登录接口---》保存用户登录状态 session:request.SESSION['name']='lqz' 签发阶段:做三件事:1 生成一个随机字符串 2 django-session表中插入记录 3 把随机字符串以cookie形式返回给前端(存在浏览器的cookie中) 认证阶段:前端自动携带cookie到后端:sessionid:随机字符串 django.contrib.sessions.middleware.SessionMiddleware 自己写的,本质原理也是session的认证机制 session是存储在服务端的键值对
流程图
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY