drf-day9

发布时间 2023-09-07 15:49:08作者: Py玩家

过滤

只针对查询所有接口

前提:必须继承 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写过滤和排序

#### 继承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

继承GenericAPIView写过滤类,可以写多个

写多个,他们是从左往右,依次执行
大原则,配置多个过滤类的时候,第一个放尽量多个过滤掉数据
配置多个:执行原理
    先执行第一个过滤类的: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# 分页方式只有一种,配置一个类即可

视图类:必须继承GenericAPIView

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(ViewSetMixin, APIView):
    authentication_classes=[]
    def list(self,request,*args,**kwargs):
        book_list=Book.objects.all()
        pagination =CommonPageNumberPagination()
        page=pagination.paginate_queryset(book_list,request)
        ser=BookSerializer(instance=page,many=True)
        return Response(ser.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是存储在服务端的键值对

 

流程图