如何在Django ModelViewSet中基于另一关联模型实现is_active过滤
完全不需要单独编写APIView,直接在现有SiteViewSet上修改即可实现/v1/site/?is_active=True的过滤需求,实现方式如下:
实现逻辑说明
AdminConfiguration中定义的is_active是Python层面的属性,无法直接用于Django ORM的数据库查询,因此需要把属性对应的判断逻辑转换为数据库可识别的查询条件,通过跨关联表的过滤即可完成需求,不需要改动原有模型,也不需要额外新增接口。
修改后的SiteViewSet代码
from django.db.models import Q from django.utils import timezone from rest_framework import viewsets class SiteViewSet(viewsets.ModelViewSet): model = Site lookup_field = 'uuid' pagination_class = PageNumberPagination serializer_class = SiteSerializer queryset = Site.objects.all() def get_queryset(self): queryset = super().get_queryset() # 读取请求中的is_active查询参数 is_active_param = self.request.query_params.get('is_active') if is_active_param is not None: # 将字符串格式的参数转为布尔值 is_active = is_active_param.strip().lower() == 'true' if is_active: # 过滤激活状态的站点:永久激活 或 订阅未过期 queryset = queryset.filter( Q(adminconfiguration__always_active=True) | Q(adminconfiguration__subscription_ends__gt=timezone.now()) ) else: # 过滤未激活状态的站点:非永久激活 且 订阅已过期 queryset = queryset.filter( Q(adminconfiguration__always_active=False) & Q(adminconfiguration__subscription_ends__lte=timezone.now()) ) return queryset
补充说明
- 如果存在
Site未关联AdminConfiguration的场景,可以根据业务需要调整过滤条件,比如新增adminconfiguration__isnull=True的分支处理,避免查询遗漏或报错。 - 上述修改完全兼容原
ModelViewSet的所有功能,原有列表查询、详情查询、创建、更新操作不受影响,只有请求携带is_active查询参数时才会触发对应过滤。
内容的提问来源于stack exchange,提问作者Esther Suh
相关产品推荐
相关产品推荐

