【DRF配置管理】如何结合ORM模糊搜索、范围查询、实现排序

原文作者:我辈李想
版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。

DRF应用和管理

【DRF配置管理】Django安装DRF框架并生成openapi风格文档
【DRF配置管理】如何实现JWT身份验证
【DRF配置管理】如何使用序列化:验证码、注册和登录
【DRF配置管理】如何结合ORM实现排序、模糊搜索、范围查询
【DRF配置管理】如何在视图类使用get_objects()
【DRF配置管理】如何实现RBAC页面菜单和按钮权限
【DRF配置管理】如何建立coreapi风格api接口文档
【DRF配置管理】如何建立swagger风格api接口文档



一、drf过滤查询

1.针对当前用户进行筛选

from myapp.models import Purchase
from myapp.serializers import PurchaseSerializer
from rest_framework import generics

class PurchaseList(generics.ListAPIView):
    serializer_class = PurchaseSerializer

    def get_queryset(self):
        """
        This view should return a list of all the purchases
        for the currently authenticated user.
        """
        user = self.request.user
        return Purchase.objects.filter(purchaser=user)

2.根据查询参数进行筛选

查询链接:http://example.com/api/purchases?username=denvercoder9

class PurchaseList(generics.ListAPIView):
    serializer_class = PurchaseSerializer

    def get_queryset(self):
        """
        Optionally restricts the returned purchases to a given user,
        by filtering against a `username` query parameter in the URL.
        """
        queryset = Purchase.objects.all()
        username = self.request.query_params.get('username')
        if username is not None:
            queryset = queryset.filter(purchaser__username=username)
        return queryset

如果想使用orm的__gte、__lte这些方法,可以在这里实现(缺陷是都需要重写),具体代码如下:
查询链接:/api/v1/sar/sarpics/?page=1&size=1&ImagingTime__gte=2020-12-22T00%3A00%3A00Z&ImagingTime__lte=2021-06-22T00%3A00%3A00Z

def get_queryset(self):
    print('gte', self.request.query_params.get('ImagingTime__gte'))
    ImagingTime__gte = self.request.query_params.get('ImagingTime__gte')
    ImagingTime__lte = self.request.query_params.get('ImagingTime__lte')
    if ImagingTime__gte:
        self.queryset = self.queryset.filter(ImagingTime__gte=ImagingTime__gte)
    if ImagingTime__lte:
        self.queryset = self.queryset.filter(ImagingTime__lte=ImagingTime__lte)
    return self.queryset

3.通用筛选-models字段查询

3.1 默认不包含__gte、__lte等条件查询

django_filters需要导入django-filter库,
查询链接:http://example.com/api/products?category=clothing&in_stock=True

import django_filters.rest_framework
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from django_filters.rest_framework import DjangoFilterBackend

class UserListView(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    filter_backends = [DjangoFilterBackend,]
	filterset_fields = ['category', 'in_stock']  # 可指定查询字段,默认无

3.2 实现__gte、__lte等查询

需要自定义FilterSet类,并在视图类中指定filterset_class。(老版本也有指定filter_class参数的,用filterset_class参数filterset_fields就需要禁用,不要同时使用)

filters.py文件

import django_filters

class ProductFilter(django_filters.FilterSet):
    name = django_filters.CharFilter(lookup_expr='iexact')  # iexact表示精确匹配, 并且忽略大小写
    author = django_filters.CharFilter(lookup_expr='icontains') #icontains表示模糊查询(包含),并且忽略大小写
    price = django_filters.NumberFilter(look_expr='exact')  #exact表示精确匹配
    desc = django_filters.CharFilter('description', lookup_expr='contains') #对'description'字段进行操作,不填默认为desc
    #price__lte = django_filters.NumberFilter('price', lookup_expr='lte') #lte表示小于
    #price__gte = django_filters.NumberFilter('price', look_expr='gte')  # gte表示大于
	class Meta:
	        model = Product
	        fields = ['name', 'author', 'price', 'description']
	        #fields = {
	             'price': ['lt', 'gt']
	        }

view.py文件

import django_filters.rest_framework
from django.contrib.auth.models import User
from myapp.serializers import UserSerializer
from rest_framework import generics
from django_filters.rest_framework import DjangoFilterBackend

class UserListView(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    filter_backends = [DjangoFilterBackend,]
	# filterset_fields = ['category', 'in_stock']  
	filterset_class = ProductFilter

4.跨表筛选

class getUserListFilter(django_filters.rest_framework.FilterSet):
    teaname = django_filters.CharFilter(field_name='tea__name', label="老师姓名") # 跨表操作
    class Meta:
        model = models.Student
        fields = ["name","teaname",]

5.模糊查询

查询链接:http://example.com/api/users?search=russell

from rest_framework import filters

class UserListView(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    filter_backends = [filters.SearchFilter]
    search_fields = ['username', 'email']

二、结合django_filters查询

参考链接:https://django-filter.readthedocs.io/en/stable/ref/filters.html

1.通用查询

在app下新建filter.py文件,写入如下内容:

import django_filters

from commodity.models import TaskMission, Task


class TaskMissionFilter(django_filters.FilterSet):
    create_time_lte = django_filters.DateTimeFilter(field_name="create_time", lookup_expr='gte')
    create_time_gte = django_filters.DateTimeFilter(field_name="create_time", lookup_expr='lte')
    rank = django_filters.CharFilter('rank', lookup_expr='contains')  # 对'notes'字段进行操作,不填默认为desc

    class Meta:
        model = TaskMission
        fields = ['create_time_lte', 'create_time_gte', 'create_time', 'demandid', 'satelliteplatform',
                  'tasknumber', 'type', 'status', 'time', 'rank']
        # fields = {'price': ['lt', 'gt']}

2.views.py中引用

@method_decorator(csrf_exempt, name="dispatch")
class TaskMissionView(MyModelViewSet):
    """
    list:
    不带路径参数获取全部
    create:
    新增一条记录
    注:因测控调用本接口接口不传状态对应时间,在新增记录时需要测控给的查询接口获取状态时间!!!
    """
    queryset = TaskMission.objects.all().order_by('-id')
    serializer_class = TaskMissionSerializer
    # 认证
    authentication_classes = [JWTAuthentication]
    # 权限
    permission_classes = []
    # 分页器
    pagination_class = MallPageNumberPagination
    # 搜索和排序
    filter_backends = [DjangoFilterBackend, OrderingFilter]
    filterset_class = TaskMissionFilter
    ordering_fields = ['create_time']
    ordering = ['-create_time']  # 默认排序

3.自定义方法

class TaskFilter(django_filters.FilterSet):
    exclude_mission_state = django_filters.CharFilter(method='exclude_state', label='排除状态')

    def exclude_state(self, queryset, field, value):
        print('value', value)
        return queryset.exclude(missiondata__mission_state__in=value)

4.__in查询

class TaskFilter(django_filters.FilterSet):
    mission_state__in = django_filters.BaseInFilter(field_name="missiondata__mission_state")

    class Meta:
        model = Task
        fields = ['mission_state__in ']
## url:http://wwwxxx.com/tasks/?mission_state__in=100,101,103

三、排序

查询链接:http://example.com/api/users?ordering=username ;
http://example.com/api/users?ordering=-username ;
http://example.com/api/users?ordering=account,username

from rest_framework.filters import OrderingFilter, SearchFilter

class UserListView(generics.ListAPIView):
    queryset = User.objects.all()
    serializer_class = UserSerializer
    filter_backends = [OrderingFilter]
    ordering_fields = ['username', 'email']
    ordering = ['username'] #默认排序
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

我辈李想

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值