背景
- django rest frameworkで認証用サービスを実装した
- 各APIへリクエストするときに、同じで認証後のユーザ情報をチェックしないといけない
- 別々でビューに書くすると重複のコードになってしまう
概要
- 別々でビューに書くすると重複のコードになってしまう
- django middleware紹介
- django middlewareで重複コードを改善する
- 例外処理
別々でビューに書くすると重複のコードになってしまう
サンプル
api_view.py
from rest_framework.views import APIView
from rest_framework.response import Response
class Contents(APIView):
def get(self, request):
try:
# トークンチェック
token_controller.check(request)
# userチェック
user = user_controller.check(request)
except Exception as e:
return Response(e)
try:
# userのコンテンツを取得
contents = content_controller.get_contents(user)
except Exception as e:
return Response(e)
return Response(contents)
- 上記のソースコードに、トークンチェックとユーザチェックが各APIにやっているので、重複な部分になってしまう
- 例外処理も重複になってしまう
- django middlewareで改善していく
django middleware紹介
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
# ビュー前の処理
response = self.get_response(request)
# ビュー後の処理
return response
- 導入
settings.py
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
......
'mymiddleware.SimpleMiddleware',
]
- middleware hooks
- process_view(request, view_func, view_args, view_kwargs)
- process_exception(request, exception)
django middlewareで重複コードを改善する
説明
- トークンチェックとユーザチェック部分をmiddlewareに移す
- 例外処理も一緒に移動して、例外発生する場合ははビューを経由しなくて直接的にエラー情報を返す
- 正常ケースの場合は、middlewareに取得したユーザ情報をkwargsで返す
ソースコード
simple_middleware.py
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def process_view(request, view_func, view_args, view_kwargs):
try:
# トークンチェック
token_controller.check(request)
# userチェック
view_kwargs["user"] = user_controller.check(request)
except Exception as e:
return Response(e)
api_view.py
from rest_framework.views import APIView
from rest_framework.response import Response
class Contents(APIView):
def get(self, request, **kwargs):
user = kwargs["user"]
try:
# userのコンテンツを取得
contents = content_controller.get_contents(user)
except Exception as e:
return Response(e)
return Response(contents)
ビューの例外処理
説明
- process_exceptionでビューに発生した例外を処理する
- ビューの方が正常ケースを処理する
ソースコード
simple_middleware.py
class SimpleMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def process_view(request, view_func, view_args, view_kwargs):
......
def process_exception(request, exception):
return Response(exception)
api_view.py
from rest_framework.views import APIView
from rest_framework.response import Response
class Contents(APIView):
def get(self, request, **kwargs):
user = kwargs["user"]
# userのコンテンツを取得
contents = content_controller.get_contents(user)
return Response(contents)
まとめ
- django middlewareを利用して結構ソースコードの量が減っている
- 例外処理も集中になって、管理しやすい
- しかし、例外発生と例外処理が別の場所なので、ソースコード実装の時に例外処理が忘れないようにしてください