You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django中PUT请求处理后重定向,能否转为GET请求获取Book数据?

Django REST Framework:修改Page后重定向到Book视图的请求方法问题

我的Django项目中存在核心模型Book及其关联的BookViewSet(基于Django REST Framework)。前端编辑Page对象时,会向对应的PageViewSet发送请求。由于修改Page会影响关联的Book,我希望在处理完Page的PUT请求后,返回更新后的BookViewSet数据。

我尝试使用redirect快捷方式跳转到BookViewSet,代码示例:return redirect('/books/10', pk=book_id),原本期望浏览器发起GET请求,通过BookViewSet的retrieve方法返回更新后的Book数据,但实际BookViewSet仍收到PUT请求,被导向update方法,导致400错误。

问题

  1. 这是预期行为吗?
  2. 若为预期行为,如何在修改Page后通过GET请求获取更新后的Book视图?我不想将retrieve方法的逻辑复制到update方法中。

我了解Post/Redirect/Get模式,但不确定需要哪些额外操作来实现GET请求。


PageViewSet代码

class PageViewSet(LoginRequiredMixin, viewsets.ModelViewSet):
    queryset = Page.objects.all()
    renderer_classes = [TemplateHTMLRenderer, JSONRenderer]
    serializer_class = PageSerializer

    def update(self, request, pk=None):
        page = self.get_object()
        page.update_layout(
            Layout.objects.get(
                id=request.data[f"{page.id}-layout"]
            )  # Form field prefix is set to page ID
        )

        return redirect("book-detail", pk=page.book.id)

控制台日志

(django.request) log/log_response: Bad Request: /books/11/
[15/Oct/2024 13:14:40] "PUT /books/11/ HTTP/1.1" 400 15

解答

问题1:这不是预期行为

Django的redirect默认返回302状态码,标准浏览器处理302响应时,会自动用GET请求重定向后的地址。你遇到的PUT请求直接发送到Book地址的情况,大概率是前端AJAX请求未正确处理302响应,而是直接将原PUT请求的方法和内容转发到了目标地址。

问题2:解决方案

有两种可靠的方式实现需求:

方式一:返回303状态码强制使用GET请求

303状态码是Post/Redirect/Get模式的标准用法,它明确告诉客户端必须用GET请求访问重定向地址。可以手动构造响应:

from django.http import HttpResponse
from django.urls import reverse

def update(self, request, pk=None):
    page = self.get_object()
    page.update_layout(
        Layout.objects.get(
            id=request.data[f"{page.id}-layout"]
        )
    )
    # 构造303响应,强制客户端发起GET请求
    response = HttpResponse(status=303)
    response['Location'] = reverse('book-detail', args=[page.book.id])
    return response
方式二:直接返回Book的序列化数据(无需重定向)

如果不需要跳转页面,只是想返回更新后的Book数据,可以在update方法中直接序列化关联的Book并返回,复用BookSerializer的逻辑:

from rest_framework.response import Response
from .serializers import BookSerializer

def update(self, request, pk=None):
    page = self.get_object()
    page.update_layout(
        Layout.objects.get(
            id=request.data[f"{page.id}-layout"]
        )
    )
    # 获取关联Book并序列化返回
    book = page.book
    serializer = BookSerializer(book, context={'request': request})
    return Response(serializer.data)

另外需要注意:如果前端是通过AJAX发起PUT请求,需要确保前端代码能正确处理303响应(自动发起GET请求),或者直接接收方式二中返回的JSON数据。


内容的提问来源于stack exchange,提问作者charliesneath

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 08:52:34