Django의 Request-Response Cycle
- Django에서는 HTTP 메시지로 요청이 들어오면 미들웨어를 거쳐 HttpRequest 객체를 만든다.
- settings.py에 있는 ROOT_URLCONF에서 urlpatterns를 순서대로 찾는다.
ROOT_URLCONF = "<your project>.urls"
- request의 url과 일치하는 패턴이 있다면 찾기를 종료하고 (클래스 기반 뷰의 경우) as_view 함수를 실행한다. (request 인자를 넘겨준다.)
# ~/login으로 찾는다면 urlpatterns = [ path("register/", member_auth_views.MemberRegisterView.as_view()), path("login/", member_auth_views.MemberLoginView.as_view()), # login과 일치한다. path("token/refresh/", TokenRefreshView.as_view()), ]
- as_view 함수 내에서 클래스 뷰를 인스턴스화 하고, view의 dispatch를 호출한다.
- dispatch는 request http method와 일치하는 함수를 실행한다.
class View:
http_method_names = [
"get",
"post",
"put",
"patch",
"delete",
"head",
"options",
"trace",
]
def __init__(self, **kwargs):
for key, value in kwargs.items():
setattr(self, key, value)
...
@classonlymethod
def as_view(cls, **initkwargs):
"""Main entry point for a request-response process."""
for key in initkwargs:
if key in cls.http_method_names:
raise TypeError(
"The method name %s is not accepted as a keyword argument "
"to %s()." % (key, cls.__name__)
)
if not hasattr(cls, key):
raise TypeError(
"%s() received an invalid keyword %r. as_view "
"only accepts arguments that are already "
"attributes of the class." % (cls.__name__, key)
)
def view(request, *args, **kwargs):
self = cls(**initkwargs) # 인스턴스화 한다.
self.setup(request, *args, **kwargs) # 인스턴스 변수를 setup한다.
if not hasattr(self, "request"):
raise AttributeError(
"%s instance has no 'request' attribute. Did you override "
"setup() and forget to call super()?" % cls.__name__
)
return self.dispatch(request, *args, **kwargs) # view의 dispatch 함수를 실행한다.
view.view_class = cls
view.view_initkwargs = initkwargs
view.__doc__ = cls.__doc__
view.__module__ = cls.__module__
view.__annotations__ = cls.dispatch.__annotations__
view.__dict__.update(cls.dispatch.__dict__)
# Mark the callback if the view class is async.
if cls.view_is_async:
markcoroutinefunction(view)
return view # as_view() -> view()를 실행하는 것과 같다.
...
def dispatch(self, request, *args, **kwargs):
# Try to dispatch to the right method; if a method doesn't exist,
# defer to the error handler. Also defer to the error handler if the
# request method isn't on the approved list.
if request.method.lower() in self.http_method_names:
handler = getattr(
self, request.method.lower(), self.http_method_not_allowed
) # request.method와 이름이 같은 method를 실행한다.
else:
handler = self.http_method_not_allowed
return handler(request, *args, **kwargs)
6. request http method와 일치하는 함수에서 비즈니스 로직을 실행하고 Response를 만든다.
7. Response는 다시 미들웨어를 통과한다.
8. 사용자에게 다시 HTTP 메시지로 응답이 간다.
배운점
- Django에서 view 인스턴스는 싱글톤으로 하나만 사용하는 것이 아닌, 요청할때마다 새로 생성된다.
- urlpatterns에서 동일한 url로 view가 여러개 있으면 처음에 있는 view가 실행된다.
참고
'Django,Python' 카테고리의 다른 글
[Django] 개발 서버는 멀티 스레드? (2) | 2024.07.09 |
---|---|
[Django] shell_plus로 개발 생산성 높이기 (0) | 2024.07.07 |
[Django] 동시성 고려하기(2) - optimistic lock 적용하기 (0) | 2024.06.10 |
[Django] 동시성 고려하기(1) - F 객체 사용하기 (0) | 2024.05.12 |
[Django] factory_boy (0) | 2024.04.16 |