Django REST类视图中如何编写多个同类型请求方法?
在Django REST类视图中处理多个同类型请求的方案
在Django REST框架里,默认一个HTTP方法(比如GET)对应类视图里的一个方法,但如果要在同一个类里处理多个同类型请求,核心是通过**请求的不同标识(路径、查询参数等)**来分发逻辑,下面是几种实用方案:
1. 通过URL路径区分
给不同的请求场景配置不同的URL路径,然后在类视图的get方法里判断当前请求的路径,执行对应逻辑。
示例代码:
urls.py
from django.urls import path from .views import ArticleView urlpatterns = [ path('articles/', ArticleView.as_view()), path('articles/popular/', ArticleView.as_view()), ]
views.py
from rest_framework.views import APIView from rest_framework.response import Response from .models import Article from .serializers import ArticleSerializer class ArticleView(APIView): def get(self, request): # 根据请求路径判断逻辑分支 if request.path.endswith('/popular/'): # 处理热门文章查询 popular_articles = Article.objects.filter(is_popular=True) serializer = ArticleSerializer(popular_articles, many=True) else: # 处理默认的所有文章查询 all_articles = Article.objects.all() serializer = ArticleSerializer(all_articles, many=True) return Response(serializer.data)
你也可以通过URL捕获参数的方式更优雅地判断,比如把URL改成path('articles/<str:category>/', ArticleView.as_view()),然后在get方法里通过request.parser_context['kwargs']['category']获取路径参数。
2. 通过查询参数区分
如果不想修改URL结构,可以用查询参数来标识不同的请求类型,比如/articles/?type=popular或/articles/?filter=recent。
示例代码:
class ArticleView(APIView): def get(self, request): # 获取查询参数,默认返回所有文章 req_type = request.query_params.get('type', 'all') if req_type == 'popular': queryset = Article.objects.filter(is_popular=True) elif req_type == 'recent': queryset = Article.objects.order_by('-created_at')[:10] else: queryset = Article.objects.all() serializer = ArticleSerializer(queryset, many=True) return Response(serializer.data)
这种方式灵活度高,不用新增路由,适合简单的分类查询场景。
3. 使用ViewSet和action装饰器(推荐)
如果你的场景是对同一资源的不同操作,Django REST的ViewSet搭配@action装饰器是更规范的REST风格方案,它可以帮你快速定义自定义的同类型请求动作。
示例代码:
views.py
from rest_framework.viewsets import GenericViewSet from rest_framework.mixins import ListModelMixin from rest_framework.decorators import action from rest_framework.response import Response from .models import Article from .serializers import ArticleSerializer class ArticleViewSet(GenericViewSet, ListModelMixin): queryset = Article.objects.all() serializer_class = ArticleSerializer # 自定义热门文章GET接口,detail=False表示是列表级动作 @action(detail=False, methods=['get']) def popular(self, request): queryset = self.get_queryset().filter(is_popular=True) serializer = self.get_serializer(queryset, many=True) return Response(serializer.data) # 自定义最近文章GET接口 @action(detail=False, methods=['get']) def recent(self, request): queryset = self.get_queryset().order_by('-created_at')[:10] serializer = self.get_serializer(queryset, many=True) return Response(serializer.data)
urls.py
from django.urls import path, include from rest_framework.routers import DefaultRouter from .views import ArticleViewSet router = DefaultRouter() router.register(r'articles', ArticleViewSet) urlpatterns = [ path('', include(router.urls)), ]
配置后会自动生成以下路由:
/articles/:默认的列表查询(GET)/articles/popular/:自定义的热门文章查询(GET)/articles/recent/:自定义的最近文章查询(GET)
这种方式代码结构更清晰,符合REST资源操作的设计规范,适合复杂的多动作场景。
内容的提问来源于stack exchange,提问作者Shaheem PP
相关产品推荐
相关产品推荐

