LoginSignup
1
0

More than 1 year has passed since last update.

django middlerwareを作ってみた

Posted at

背景

  • 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を利用して結構ソースコードの量が減っている
  • 例外処理も集中になって、管理しやすい
  • しかし、例外発生と例外処理が別の場所なので、ソースコード実装の時に例外処理が忘れないようにしてください
1
0
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
1
0