개요
2024.06.13-[Python] Tornado 란에서 Tornado 웹 애플리케이션의 기본적인 구조와 실행 방법에 대해서 정리했었는데, 이번 글에서는 Tornado 웹 애플리케이션의 주요 요소 중 하나인 RequestHandler에 대해서 적어본다.
RequestHandler
Tornado 애플리케이션의 대부분의 작업은 RequestHandler의 서브 클래스에서 수행된다.
RequestHandler의 주 진입점은 HTTP 메서드 이름을 딴 get, post 등이 되며, 메서드는 하나 이상 정의할 수 있다.
응답은 RequestHandler.render, RequestHandler.write 등의 함수를 호출하여 생성하는데, 두 함수는 각각 용도에 따라 호출하면 된다.
- RequestHandler.render : 이름 별로 템플릿을 로드하고 주어진 매개변수로 이를 렌더링 한다.
- RequestHandler.write : 문자열, 바이트, 딕셔너리, JSON 등 비템플릿 기반 출력을 위해 사용한다.
일반적으로는 RequestHandler를 상속받아 사용자가 애플리케이션 내에서 공용으로 사용할 BaseHandler를 정의하고, 정의한 BaseHandler의 하위 클래스를 만들어 애플리케이션을 구현하는 방식으로 구현하게 된다.
입력 Form 데이터 접근
Tornado 애플리케이션에서 요청 객체 HTTPServerRequest는 RequestHandler의 self.request 속성을 통해 접근할 수 있다.
참고로 HTML Form에서 사용되는 형식의 데이터는 get_query_argument, get_query_arguments, get_body_argument, get_body_arguments 메소드에서 사용할 수 있도록 파싱 된다.
- get_query_argument : 요청 쿼리 문자열에서 주어진 이름의 변수 값을 반환한다.
- get_body_argument : 요청 body에서 주어진 이름의 변수 값을 반환한다.
예시로 아래와 같이 간단한 입력 폼을 만들었다고 하자.
from tornado.web import Application, RequestHandler
from tornado.ioloop import IOLoop
class MainHandler(RequestHandler):
def get(self):
self.write('<html><body><form action="/myform" method="POST">'
'<input type="text" name="message">'
'<input type="submit" value="Submit">'
'</form></body></html>')
def make_app():
return Application([
(r"/", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
IOLoop.current().start()
이 폼에 입력한 메시지는 아래와 같이 접근할 수 있다.
class MainHandler(RequestHandler):
def post(self):
self.set_header("Content-Type", "text/plain")
self.write("You wrote " + self.get_body_argument("message"))
def make_app():
return Application([
(r"/myform", MainHandler),
])
아래 사진은 폼에서 test라는 문자열을 입력했을 때의 응답이다.
위 예시의 전체 소스는 접은글로 적어둔다.
from tornado.web import Application, RequestHandler
from tornado.ioloop import IOLoop
class MainHandler(RequestHandler):
def get(self):
self.write('<html><body><form action="/myform" method="POST">'
'<input type="text" name="message">'
'<input type="submit" value="Submit">'
'</form></body></html>')
def post(self):
self.set_header("Content-Type", "text/plain")
self.write("You wrote " + self.get_body_argument("message"))
def make_app():
return Application([
(r"/", MainHandler),
(r"/myform", MainHandler),
])
if __name__ == "__main__":
app = make_app()
app.listen(8888)
IOLoop.current().start()
폼에서 입력된 데이터가 파일인 경우에는 업로드된 파일의 상태에 따라 접근 방법이 조금 다르다.
<input type="file"> 태그와 multipart/form-data Content-Type으로 지정되어 업로드된 파일은 filename, content_type, body로 구성된 딕셔너리인 self.request.files 속성으로 접근할 수 있다.
multipart/form-data를 지정하지 않았을 때는 self.request.body 속성으로 접근할 수 있다.
참고 문서
https://www.tornadoweb.org/en/branch6.1/guide/structure.html