[Django] RedirectViewについて詳しく見てみる

以前TemplateViewについて詳しく見てみたわけですが、今度はRedirectViewについて見てみたいと思います。

Django(GitHub)
https://github.com/django/django

RedirectView

RedirectViewの実装はTemplateViewと同じくdjango/django/views/generic/base.pyに書いてあります。

その中から重要そうなところを抜粋

class RedirectView(View):
    permanent = False
    url = None
    pattern_name = None
    query_string = False

    def get_redirect_url(self, *args, **kwargs):
        if self.url:
            url = self.url % kwargs
        elif self.pattern_name:
            url = reverse(self.pattern_name, args=args, kwargs=kwargs)
        else:
            return None

        args = self.request.META.get('QUERY_STRING', '')
        if args and self.query_string:
            url = "%s?%s" % (url, args)
        return url

    def get(self, request, *args, **kwargs):
        url = self.get_redirect_url(*args, **kwargs)
        if url:
            if self.permanent:
                return HttpResponsePermanentRedirect(url)
            else:
                return HttpResponseRedirect(url)
        else:
            logger.warning(
                'Gone: %s', request.path,
                extra={'status_code': 410, 'request': request}
            )
            return HttpResponseGone()

    def head(self, request, *args, **kwargs):
        return self.get(request, *args, **kwargs)

    def post(self, request, *args, **kwargs):
        return self.get(request, *args, **kwargs)

    def options(self, request, *args, **kwargs):
        return self.get(request, *args, **kwargs)

    def delete(self, request, *args, **kwargs):
        return self.get(request, *args, **kwargs)

    def put(self, request, *args, **kwargs):
        return self.get(request, *args, **kwargs)

    def patch(self, request, *args, **kwargs):
        return self.get(request, *args, **kwargs)

他の全てのhttpリクエストに対してGETメソッドと同じように動作するように定義されています。

GETメソッドではリダイレクトをかけています。
HttpResponsePermanentRedirectHttpResponseRedirectがそれにあたります。

リダイレクト先を指定する

クラス変数urlにリダイレクト先のurlを指定します。

class RedirectGoogle(RedirectView):
    url = "https://google.com"

直接文字列を指定する代わりにdjango.urls.reverse_lazyと組み合わせればサイト内の別ページへリダイレクトさせることもできます。

class RedirectTopPage(RedirectView):
    url = reverse_lazy("top_page")

一時的なリダイレクト

デフォルトでは一時的なリダイレクト(302)になっているので特に何かする必要はありません。

恒久的なリダイレクト

クラス変数permanentをTrueにすると恒久的なリダイレクト(301)に出来ます。

class RedirectTopPage(RedirectView):
    url = reverse_lazy("top_page")
    permanent = True

クエリ文字列を引き継ぐ

ここで言う、クエリ文字列というのはURLの後ろにくっついている?以降のid=1&string=strみたいなやつの事です。
クラス変数query_stringをTrueにすることでそのページにアクセスしてきた時のクエリをリダイレクト先に引き継ぐことができます。

class RedirectTopPage(RedirectView):
    url = reverse_lazy("top_page")
    query_string = True

まとめ

  • デフォルトのリダイレクトを表すhttpステータスコードは302(一時なリダイレクト)
  • クラス変数permanentTrueにするとhttpステータスコード301(恒久的なリダイレクト)を返すことが出来る。
  • クラス変数query_stringtrueにするとクエリ文字列を引き継いでリダイレクトできる