Почему Django HTTPResponseRedirect использует один и тот же HTTP-метод для PUT, но не POST?

У меня есть проект Django, где я использую представление для обработки различных HTTP-методов. POST обрабатывал создание объекта, а затем перенаправлялся на тот же вид, что и GET (или так я думал), используя Django redirect() shortcut (HTTPResponseRedirect), чтобы вернуть вновь созданный объект. Это отлично работает. Я пробовал то же самое с PUT, но я попал в цикл перенаправления. Некоторое время царапая голову, я наткнулся на этот ответ SO, а затем я предположил, что, поскольку перенаправление не обрабатывает данные POST, запрос превращается в GET.

Я подтвердил это, просмотрев журналы, когда я делаю перенаправление с POST:

[15/Dec/2014 00:47:43] "POST /client/151/ HTTP/1.1" 302 0
[15/Dec/2014 00:47:43] "GET /client/151/ HTTP/1.1" 200 395

Однако PUT остается a PUT и бросает меня в цикл перенаправления до тех пор, пока он не выйдет из строя.

[14/Dec/2014 23:07:36] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:37] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:37] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:38] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:38] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:39] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:39] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:40] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:40] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:41] "PUT /api/asset/6779/ HTTP/1.1" 302 0
[14/Dec/2014 23:07:41] "PUT /api/asset/6779 HTTP/1.1" 301 0
[14/Dec/2014 23:07:42] "PUT /api/asset/6779/ HTTP/1.1" 302 0

Не следует ли использовать перенаправление GET? Я понимаю, что происходит, но не знаю почему? Что дает?

ИЗМЕНИТЬ

# urls.py
url(r'^$', views.put_vs_post_redirect),

# views.py
from django.shortcuts import redirect

def put_vs_post_redirect(request, asset_id):

    if request.method == 'GET':
        return HTTPResponse('Get request')     
    elif request.method == 'POST':
        return redirect('/')
    elif request.method == 'PUT':
        return redirect('/')

Ответ 1

Как уже упоминалось в комментариях, это полностью зависит от клиента, и не все клиенты обрабатывают переадресации таким же образом. Вы можете найти достойное объяснение кодов переадресации и почему 301 должен удалить данные POST в Stack Overflow.

При работе с перенаправлением 301 (и часто 302) большинство браузеров будут отбрасывать данные POST и делать запрос GET. Это происходит главным образом потому, что браузеры всегда это делали, а POST запросы чаще всего поступают из веб-форм, поэтому имеет смысл, что перенаправление приводит к GET, позволяя браузеру отображать другую страницу без вмешательства. Это не относится к вещам типа PUT или PATCH запросов, поскольку они в настоящее время не могут быть отправлены с помощью веб-форм и обычно играют по разным правилам.

Если вы хотите сохранить данные POST при перенаправлении 302, вы должны рассмотреть с помощью 307 redirect вместо. Запрос 307 должен поддерживать метод запроса и тело запроса в результате.

Если вы хотите сохранить данные POST в перенаправлении 301, в настоящее время черновик для кода состояния 308, который будет работать как 307, но будет постоянным.

Вы можете заставить перенаправление использовать запрос GET с a 303 redirect. Он очень похож на 302, но он гарантирует, что метод запроса всегда является запросом GET. Он часто используется в API для асинхронных задач.