3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Djangoで指定したhostにリダイレクトさせるmiddlewareを書いた(middleware入門)

Posted at

TL;DR

タイトル通り、Djangoで指定したhostにリダイレクトさせるmiddlewareを書こうとした。
見つかった記事が5年以上前のものと古く、Django v1.10以降のmiddlewareの書き方に対応していなかったので対応する書き方で書き直した。
middlewareで呼ばれる関数についてはこちらがわかりやすかった。

0.問題設定

例えばDjangoアプリケーションをherokuでデプロイし(example.herokuapp.com)、お名前.comでドメイン(example.com)を取得したとする。
この場合、example.comからアクセスできるようになったとしても、
example.herokuapp.comでも同様にアクセスできる。
これをリダイレクトするために、middlewareを作って対応した。

1.middleware作成

今回、プロジェクト直下に/lib/middleware.py という名前でmiddlewareを作成。
クラス名はRedirectCorrectHostname とする。
これを/{プロジェクト名}/settings.pyに追加する。

settings.py
MIDDLEWARE = [
    ...
    'lib.middleware.RedirectCorrectHostname',
    ...
]

ここがハマりポイント1で、v1.10より、MIDDLEWARE_CLASSESからMIDDLEWAREに変わった。(参考)

2.リダイレクト先のhostを指定

settings.py
CORRECT_HOST = '127.0.0.1:8000'

これをsettings.CORRECT_HOST として参照できる。

3.リダイレクトのmiddlewareを定義

middleware.py
from django.http import HttpResponsePermanentRedirect
from django.conf import settings


class RedirectCorrectHostname(object):
    def __init__(self, get_response):
        self.get_response = get_response

    def __call__(self, request):
        response = self.get_response(request)
        return response

    def process_view(self, request, view_func, view_args, view_kwargs):
        # settingsにCORRECT_HOSTがあるか
        if not getattr(settings, 'CORRECT_HOST', None):
            return None
        # settings.CORRECT_HOSTとアクセスしているhostが一致するか
        if request.get_host() == settings.CORRECT_HOST:
            return None

        # 一致しなかった場合、settings.CORRECT_HOSTにリダイレクト
        return HttpResponsePermanentRedirect(
            '{scheme}://{host}{path}'.format(scheme=request.scheme,
                                             host=settings.CORRECT_HOST,
                                             path=request.get_full_path()))

詳しい説明はこちらを参照してほしいのだが、各メソッドについて軽く説明。

__init__

サーバ起動時に1度だけ呼び出される。初期化。必須。

__call__

リクエスト毎に呼び出されるメソッド。必須。
self.get_response() 実行前に処理を記述することで、view関数適用前に実行する共通処理を定義することができる。

process_view

view関数を呼び出す直前にhookされるメソッド。

  • 実行されるview関数
  • そのview関数への引数(例えばurlsで定義したパラメータ)

を知っている。
返り値として

  • None
  • HttpResponse

のどちらかを返す必要があり、ここにリダイレクト処理を定義した。

おわりに

リダイレクト処理なんて何人もやってそうなのに意外と記事がなかった......

参考

元記事
middlewareの関数
MIDDLEWARE_CLASSESからMIDDLEWAREへ

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?