naritoブログ

このブログはDjangoとBootstrap4で作成されました
ソースコード

Django、リダイレクト時にGETパラメータも渡す

プログラミング関連 Django Python 約254日前
2017年4月2日0:57
Djangoで、リダイレクトを行う場合は概ね2つの方法があります。


django.http.HttpResponseRedirect


まずHttpResponseRedirectです。あまり使う機会は多くないです。
引数にURLを指定する必要があり、記述も長くなります。基本的には後述のredirectを使うことになるでしょう。
return HttpResponseRedirect('http://exmaple.com')



django.shortcuts.redirect


このredirectを使うのが一番多いと思います。
reverse()で解釈できる文字列や、URLを渡したり、 get_absolute_url()を持たせたオブジェクトなんかも渡せます。
ちなみにですが、この動作はredirect関数というより内部でのresolve_url()による働きです。(django.shortcuts.resolve_url)
object = MyModel.objects.get(...)
return redirect(object)
return redirect('/some/url/')
return redirect('http://example.com/')


実際のところ、redirectでやっているのは以下のようなコードです。
    redirect_class = HttpResponsePermanentRedirect if permanent else HttpResponseRedirect
    return redirect_class(resolve_url(to, *args, **kwargs))



例えば以下のようなurlへリダイレクトさせたいならば
urlpatterns = [
    url(r'^update/(?P<pk>[0-9]+)/$', views.PostUpdate.as_view(), name='post_update'),
]


このようにリダイレクトができていました。
return redirect('post_update', pk=1)

url = resolve_url('post_update', pk=1)
return HttpResponseRedirect(url)


では、もし以下のようなGETパラメータつきのURLを、違うビューにGETパラメータをつけたまま転送したい場合はどうでしょう。
http://127.0.0.1:8000/test?food=sushi&time=19


まずはredirectやHttpResponseRedirectについてみてみましょう。
from django.http import HttpResponseRedirect
from django.shortcuts import redirect, resolve_url


def test(request):
    # response = HttpResponseRedirect(resolve_url('index'))  # 下と同義
    response = redirect('index')  # indexは/です
    print(response)
    print(response.__dict__)
    return response


すると、以下のような結果になりました。なにやらlocationとやらが怪しいです。(pprintで見やすくしました。)
<HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/">
{'_charset': None,
 '_closable_objects': [],
 '_container': [b''],
 '_handler_class': None,
 '_headers': {'content-type': ('Content-Type', 'text/html; charset=utf-8'),
              'location': ('Location', '/')},
 '_reason_phrase': None,
 'closed': False,
 'cookies': <SimpleCookie: >}



このlocationへのアクセスが面倒に思うかもしれませんが、実は以下のようにすんなりアクセスできます。
response['location'] = 'aaa'


HttpResponseBaseという基底クラスで、以下のようにしてあるためです。
とにかく、今回は単純にアクセスができます。
    def __getitem__(self, header):
        return self._headers[header.lower()][1]


後は簡単です。request.GET.urlencode()でGETパラメータの文字列を取得し、
response['location'] += get_paramsで、リダイレクト先のURLにGETパラメータの文字列を足すだけです。
    response = redirect('post_list')
    get_params = request.GET.urlencode()
    response['location'] += '?'+get_params
    return response


他によく使うのはcopy()なんかを使い、GETパラメータの書き換えを行う例です。
request.GET(request.POSTも)はQueryDictという辞書っぽいオブジェクトで、copy()はそのコピーを返します。
こちらも余裕があれば目を通しましょう。
https://docs.djangoproject.com/en/1.10/ref/request-response/
http://docs.djangoproject.jp/en/latest/ref/request-response.html