drf过滤,排序,分页,异常处理

发布时间 2023-05-25 20:25:11作者: 哈哈哈哼

django中的翻译函数

# 只要做了国际化,会自动翻译成,当前国家的语言
from django.utils.translation import gettext_lazy as _
_('hello')

过滤

# restful规范中
	-请求地址中带过滤条件
    
# 带过滤的接口只有:查询所有


# 内置过滤类

from rest_framework.filters import SearchFilter
class BookView(GenericViewSet, ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerialzier
    filter_backends = [SearchFilter]
    # 支持这种搜索
    # # http://127.0.0.1:8000/api/v1/books/?search=红
    # search_fields = ['name']

    #http://127.0.0.1:8000/api/v1/books/?search=11  只要name或price中带11都能搜出来
    search_fields = ['name','price']

# 第三方过滤类
### 2.1 第三方过滤类
# pip3 install django-filter
from django_filters.rest_framework import DjangoFilterBackend
class BookView(GenericViewSet, ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerialzier
    filter_backends = [DjangoFilterBackend]
    # http://127.0.0.1:8000/api/v1/books/?name=红楼梦&price=45
    # 按名字和价格精准匹配
    filterset_fields = ['name', 'price']



# 自定义过滤类   价格再100----200之间的图书
from .filter import MyFilter
class BookView(GenericViewSet, ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerialzier
    filter_backends = [MyFilter]
	# 必须配合一个过滤类
    
from rest_framework import filters
from django.db.models import Q
class MyFilter(filters.BaseFilterBackend):
    def filter_queryset(self, request, queryset, view):
        # 返回的数据,就是过滤后的数据
        # http://127.0.0.1:8000/api/v1/books/?price=44&name=红楼梦   按名字或价格
        price = request.query_params.get('price')
        name = request.query_params.get('name')
        queryset = queryset.filter(Q(name=name) | Q(price=price))
        return queryset

    
 # 过滤和排序可以一起使用

排序

# restful规范中
	-请求地址中带过滤条件
# 排序功能的接口:查询所有


from rest_framework.filters import OrderingFilter

class BookView(GenericViewSet, ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerialzier
    filter_backends = [OrderingFilter]  # 排序类
    # 配合一个类属性,按哪些字段可以排序
    # http://127.0.0.1:8000/api/v1/books/?ordering=-price,-id
    # 先按价格倒序排,价格一样,再按id倒叙排
    ordering_fields = ['price','id']

分页

# 查询所有接口,过滤和排序了,但是实际上,这个接口,都需要有分页功能
	-分页的展现形式
    	web:下一页点解
        app,小程序:下滑下一页
    -接口都一样,要支持分页
    
    

# drf提供给咱们,三种分页方式
# 基本分页
# 偏移分页
# 游标分页


from .page import MyPageNumberPagination,MyLimitOffsetPagination,MyCursorPagination
# 这种方式用的多
class BookView(GenericViewSet, ListModelMixin):
    queryset = Book.objects.all()
    serializer_class = BookSerialzier
    # http://127.0.0.1:8000/api/v1/books/?page=2&page_size=3
    # pagination_class = MyPageNumberPagination  # 只能按一种方式分页,不要放到列表中了

    # http://127.0.0.1:8000/api/v1/books/?limit=4&offset=3  # 从第三条数据开始,取4条
    # pagination_class = MyLimitOffsetPagination  # 只能按一种方式分页,不要放到列表中了


    pagination_class = MyCursorPagination  # 只能按一种方式分页,不要放到列表中了

    
    
 #### page.py
from rest_framework.pagination import PageNumberPagination, LimitOffsetPagination, CursorPagination


## 基本分页
class MyPageNumberPagination(PageNumberPagination):
    # 重写几个类属性 :4个
    page_size = 2  # 每页显示的条数
    page_query_param = 'page'  # page=4 表示第4页
    page_size_query_param = 'page_size'  # page=4&page_size=5 表示查询第4页,每页显示5条
    max_page_size = 5  # 每页最大显示多少条


## 偏移分页
class MyLimitOffsetPagination(LimitOffsetPagination):
    # 重写几个类属性 :4个
    default_limit = 2  # 每页显示多少条
    limit_query_param = 'limit'  # limit=3  这一页取3条
    offset_query_param = 'offset'  # 偏移量是多少  offset=3&limit=2  从第3条开始,拿2条
    max_limit = 5  # 最多取5条


## 游标分页,只能上一页和下一页,不能直接跳到某一页,但是这个的速度快---》app上用它多
class MyCursorPagination(CursorPagination):
    # 重写几个类属性 :3个
    cursor_query_param = 'cursor'  # 查询参数,其实用不到
    page_size = 2  # 每页显示多少条
    ordering = 'id'  # 必须是要分页的数据表中的字段,一般按id来

异常处理

# APIView--->dispatch--->三大认证,视图类的方法,如果出了一场,会被一场捕获,捕获后统一处理
# drf 内置了一个函数,只要上面过程出了异常,就会执行这个函数,这个函数只处理的drf的异常
	-主动抛的非drf异常
    -程序出错了 
    都不会被处理
    我们的目标,无论主动抛还是程序运行出错,都同意返回规定格式--》能记录日志
    公司里一般返回   {code:999,'msg':'系统错误,请联系系统管理员'}
    
    
    
# 写一个函数,内部处理异常,在配置文件中配置一下即可

def common_exception_handler(exc, context):
    # exc 错误对象
    # context:上下文,有view:当前出错的视图类的对象,args和kwargs视图类方法分组出来的参数,request:当次请求的request对象
    # 只要走到这里,就要记录日志 ,只有错了,才会执行这个函数
    # 记录日志尽量详细
    print('时间,登录用户id,用户ip,请求方式,请求地址,执行的视图类,错误原因')
    res = exception_handler(exc, context)
    if res:  # 有值,说明返回了Response 对象,没有值说明返回None
        # 如果是Response 对象说明是drf的异常,已经被处理了,如果是None表明没有处理,就是非drf的异常
        res = Response(data={'code': 888, 'msg': res.data.get('detail', '请联系系统管理员')})
    else:
        # res = Response(data={'code': 999, 'msg': str(exc)})
        # 记录日志
        res = Response(data={'code': 999, 'msg': '系统错误,请联系系统管理员'})


    return res


# 在配置文件中配置
REST_FRAMEWORK = {
	'EXCEPTION_HANDLER': 'app01.exceptions.common_exception_handler',
}