Django REST Framework中实现POST返回201后重定向的类视图
实现提交请假申请后返回201并重定向至待审批页面
嘿,我来帮你搞定这个需求!要实现员工提交请假申请后返回201状态码,同时跳转到/pending_for_approval页面并展示申请内容,分两种常见场景来处理,看你是用普通Django服务器渲染页面,还是前后端分离的API架构:
场景1:普通Django服务器端渲染(适合传统页面提交)
这种场景下,我们用Django的CreateView处理表单提交,并重定向到详情页面展示申请内容,同时满足状态码的要求。
步骤1:配置URL路由
先给提交申请和待审批页面配置URL:
# urls.py from django.urls import path from .views import LeaveApplyView, LeavePendingView urlpatterns = [ path('apply-leave/', LeaveApplyView.as_view(), name='apply_leave'), # 带申请ID的待审批页面,用来展示具体申请内容 path('pending_for_approval/<int:pk>/', LeavePendingView.as_view(), name='pending_for_approval'), ]
步骤2:编写提交申请的类视图
重写CreateView的form_valid方法,保存申请后重定向到待审批页面,同时调整状态码(注:HTTP规范中POST后重定向建议用303状态码,但如果你坚持要返回201,也可以修改):
# views.py from django.views.generic.edit import CreateView from django.shortcuts import redirect from django.urls import reverse from .models import Leave from .forms import LeaveApplyForm class LeaveApplyView(CreateView): model = Leave form_class = LeaveApplyForm # 你需要提前定义这个表单类 def form_valid(self, form): # 保存用户提交的请假申请,自动关联当前登录员工 self.object = form.save(commit=False) self.object.employee = self.request.user.employee self.object.save() # 生成待审批页面的跳转链接 redirect_url = reverse('pending_for_approval', kwargs={'pk': self.object.pk}) response = redirect(redirect_url) # 如果你需要严格返回201状态码(虽然不符合重定向的HTTP规范) # response.status_code = 201 # 更合规的做法是用303状态码(POST请求后重定向,客户端会用GET请求目标页面) response.status_code = 303 return response
步骤3:编写待审批页面的详情视图
用DetailView展示员工提交的申请内容,同时添加权限控制确保只有申请人能查看:
# views.py from django.views.generic.detail import DetailView from django.core.exceptions import PermissionDenied from .models import Leave class LeavePendingView(DetailView): model = Leave template_name = 'leave/pending_for_approval.html' # 你的模板文件路径 context_object_name = 'leave_application' # 模板中用来调用申请对象的变量名 def get_object(self, queryset=None): obj = super().get_object(queryset) # 验证当前用户是申请的提交人 if obj.employee != self.request.user.employee: raise PermissionDenied("你无权查看该申请") return obj
步骤4:编写待审批页面模板
在pending_for_approval.html中展示申请内容:
<!-- templates/leave/pending_for_approval.html --> <h1>申请已提交,等待审批</h1> <div class="application-details"> <p><strong>申请人:</strong>{{ leave_application.employee.name }}</p> <p><strong>请假类型:</strong>{{ leave_application.leave_type }}</p> <p><strong>开始日期:</strong>{{ leave_application.start_date|date:"Y-m-d" }}</p> <p><strong>结束日期:</strong>{{ leave_application.end_date|date:"Y-m-d" }}</p> <p><strong>申请理由:</strong>{{ leave_application.reason }}</p> </div>
场景2:Django REST Framework API(前后端分离)
如果是前后端分离的架构,API返回201状态码的同时,告诉前端要跳转的页面地址,有两种方式:
方式1:通过响应头返回跳转地址
在CreateAPIView中添加Location响应头,前端可以读取该头进行跳转:
# views.py from rest_framework.generics import CreateAPIView from rest_framework.response import Response from rest_framework import status from rest_framework.permissions import IsAuthenticated from django.urls import reverse from .models import Leave from .serializers import LeaveSerializer class LeaveApplyAPI(CreateAPIView): queryset = Leave.objects.all() serializer_class = LeaveSerializer permission_classes = [IsAuthenticated] # 只允许登录用户提交 def perform_create(self, serializer): # 自动关联当前登录员工 serializer.save(employee=self.request.user.employee) def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) # 生成待审批页面的绝对URL pending_url = reverse('pending_for_approval', kwargs={'pk': serializer.instance.pk}) absolute_url = request.build_absolute_uri(pending_url) # 添加Location响应头 headers['Location'] = absolute_url # 返回201状态码和申请数据,同时带跳转地址头 return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
方式2:在响应体中返回跳转地址
如果前端更倾向于从响应体获取跳转地址,可以在返回的JSON中添加redirect_url字段:
def create(self, request, *args, **kwargs): serializer = self.get_serializer(data=request.data) serializer.is_valid(raise_exception=True) self.perform_create(serializer) headers = self.get_success_headers(serializer.data) pending_url = reverse('pending_for_approval', kwargs={'pk': serializer.instance.pk}) absolute_url = request.build_absolute_uri(pending_url) # 把跳转地址加入响应数据 response_data = serializer.data response_data['redirect_url'] = absolute_url return Response(response_data, status=status.HTTP_201_CREATED, headers=headers)
之后前端可以根据redirect_url字段跳转到待审批页面,页面可以通过API获取申请详情并展示。
内容的提问来源于stack exchange,提问作者Philip Mutua
相关产品推荐
相关产品推荐

