Django 3.x버전을 최신 4.1버전으로 update하면서 기존 Django버전에 dependency한 library들도 같이 update했다.

그러면서 여러가서 호환문제가 발생했는데 그중에 하나가

request.is_ajax가 3.X이상에서 deprecated되면서 AttributeError: 'WSGIRequest' object has no attribute 'is_ajax' 에러 발생하는 것이다.

그래서 기존 sns인증 처리 모듈에서 사용하던 is_ajax는 어떻게 대체했는지 소스를 봤더니

/Lib/site-packages/allauth/account/adapter.py

버전업전 : django-allauth 0.41.0

    def is_ajax(self, request):
        return request.is_ajax()

버전업후 : django-allauth 0.51.0

    def is_ajax(self, request):
        return any(
            [
                request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest",
                request.content_type == "application/json",
                request.META.get("HTTP_ACCEPT") == "application/json",
            ]
        )

위 와같이 ajax호출 여부를 판단하고 있었다.

문제는 기존 소스에 있는 is_ajax부분을 어떻게 대체할 것인가 인데... 유틸성함수로 하지않고, Django의 middleware로 해결하는 방법을 찾았다.

 

settings.py

MIDDLEWARE = [
...
    'Blog.middleware.CustomMiddleware',
...
]

 

Blog/middleware.py

# https://docs.djangoproject.com/en/4.1/topics/http/middleware/#middleware
class CustomMiddleware:
    
    # Called once at startup
    def __init__(self, get_response):
        self.get_response = get_response
        
    # Called every time on request
    def __call__(self, request):
        def is_ajax(self):
            return any(
                        [
                            request.META.get("HTTP_X_REQUESTED_WITH") == "XMLHttpRequest",
                            request.content_type == "application/json",
                            request.META.get("HTTP_ACCEPT") == "application/json",
                        ]
                    )
        
        request.is_ajax = is_ajax.__get__(request)
        response = self.get_response(request)
        return response

 

이렇게 하면 request호출시 마다 __call__이 호출되면서 request객체에 is_ajax이름의 callable한 함수를 넣어 준다.

그렇게 되면 기존 소스상 아래와 같이 사용하던 부분은 수정없이 그대로 사용할 수 있다.

if request.is_ajax():

 

callable한 객체함수 사용법 참조 : https://blog.daonelab.com/post/11/1847/