Django Rest Framework自定义ViewSet实现按年份查询节假日
完善DRF按年份查询节假日的自定义视图实现
我来帮你把这个按年份查询节假日的视图补全并优化,咱们一步步来:
1. 补全基础配置与代码细节
首先你的ViewSet需要指定queryset和serializer_class(这是GenericViewSet的必填项),同时补全代码里的拼写遗漏,再完善参数校验和响应逻辑:
from rest_framework import mixins, viewsets from rest_framework.decorators import action from rest_framework.response import Response from datetime import date # 请替换成你实际的模型和序列化器 from .models import Holiday from .serializers import HolidaySerializer class HolidayViewSet(mixins.RetrieveModelMixin, viewsets.GenericViewSet): queryset = Holiday.objects.all() serializer_class = HolidaySerializer @action(methods=['get'], detail=False) def year(self, request): # 从请求参数获取年份,默认使用当前年份 year_param = request.query_params.get('year', date.today().year) # 校验年份参数的有效性 try: year = int(year_param) # 可根据业务需求添加年份范围限制,比如只允许查询2000年至未来5年的节假日 if not (2000 <= year <= date.today().year + 5): return Response({"error": "年份超出合理查询范围"}, status=400) except ValueError: return Response({"error": "请传入有效的数字年份"}, status=400) # 筛选对应年份的节假日 public_holidays = self.get_queryset().filter(date__year=year) # 处理分页逻辑 page = self.paginate_queryset(public_holidays) if page is not None: serializer = self.get_serializer(page, many=True) return self.get_paginated_response(serializer.data) # 不分页时直接返回全部结果 serializer = self.get_serializer(public_holidays, many=True) return Response(serializer.data)
2. 关键优化点说明
- 替换旧版装饰器:把过时的
@list_route()换成DRF 3.10+推荐的@action(methods=['get'], detail=False),detail=False表示这是列表级别的接口,而非单条数据的详情接口。 - 灵活的参数获取:采用
query_params获取年份参数,前端可以通过/api/holidays/year/?year=2024的方式请求,比路径参数更灵活;如果需要用路径传参(比如/api/holidays/year/2024/),可以修改方法定义为def year(self, request, year):并配置对应路由。 - 参数校验:增加了年份格式和范围校验,避免无效参数导致数据库查询异常,同时返回友好的错误提示。
- 完整响应逻辑:兼容分页与不分页场景,若你开启了DRF全局分页配置,会自动返回分页结构;否则直接返回全部数据。
3. 路由配置(可选)
如果使用DRF的DefaultRouter,它会自动为@action生成路由,默认访问路径是/holidays/year/。若想自定义路径,可以在装饰器中添加url_path参数,比如@action(methods=['get'], detail=False, url_path='by-year'),此时访问路径变为/holidays/by-year/。
内容的提问来源于stack exchange,提问作者Ron
相关产品推荐
相关产品推荐

