[Django] リダイレクト時のステータスコードを307、308にする

Djangoではリダイレクトを意味するステータスコードは旧来の301、302が採用されているので、これを新しいステータスコードに置き換える方法のメモです

Djangoデフォルトのリダイレクト

まず、Djangoのリダイレクトはどんな実装になっているかチェックしてみます。

class HttpResponseRedirectBase(HttpResponse):
    allowed_schemes = ['http', 'https', 'ftp']

    def __init__(self, redirect_to, *args, **kwargs):
        super().__init__(*args, **kwargs)
        self['Location'] = iri_to_uri(redirect_to)
        parsed = urlparse(str(redirect_to))
        if parsed.scheme and parsed.scheme not in self.allowed_schemes:
            raise DisallowedRedirect("Unsafe redirect to URL with protocol '%s'" % parsed.scheme)

    url = property(lambda self: self['Location'])

    def __repr__(self):
        return '<%(cls)s status_code=%(status_code)d%(content_type)s, url="%(url)s">' % {
            'cls': self.__class__.__name__,
            'status_code': self.status_code,
            'content_type': self._content_type_for_repr,
            'url': self.url,
        }


class HttpResponseRedirect(HttpResponseRedirectBase):
    status_code = 302


class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
    status_code = 301

Django公式のリポジトリから一部抜粋してきました。

クラス変数status_code部分でhttpステータスコードをコントロールしているようです。

ステータスコード部分を書き換えるだけでかなり簡単に変更できそうです。

一時的なリダイレクト(307)

class HttpResponseRedirect(HttpResponseRedirectBase):
    status_code = 307

恒久的なリダイレクト(308)

class HttpResponsePermanentRedirect(HttpResponseRedirectBase):
    status_code = 308

最後に

Djangoのリダイレクト時のステータスコードを307、308にする方法をご紹介しました。

そうそういないとは思いますが、超古代のブラウザなどでは新しいステータスコードに対応していない場合も考えられるので、基本的には自分でステータスコードをいじる必要はないです。

ソースコードを見る限りでは、クラス変数status_codeを他の値に書き換えれば、他のhttpレスポンスも簡単に返せそうです。