오답노트

[Django] Django Form 본문

Python/Django

[Django] Django Form

권멋져 2022. 11. 17. 23:51

GET 과 POST

HTML에서 요청을 하는 방식중에 GET 과 POST 라는 것들이 존재한다. 나중에 REST를 참고하여 공부해보자.

 

GET은 요청정보 헤더에 담겨 전달되는 방식이다. 따라서 전달하려는 정보다 노출이 되고, 길이에도 제한이 있다.

POST는 요청정보 바디에 담겨 전달되는 방식이다. 따라서 전달하려는 정보를 은폐할 수 있고, 길이 제한도 없다.

 

위에서 비교를 보면 POST가 더 좋아보이지만, GET은 정보를 조회할 때, POST는 정보를 생성할 때 자주 사용된다.(예외도 물론 존재함)

 

CSRF (Cross-Site Request Forgery)

예전에는 GET방식으로 로그인도 하고 그래서 개인정보 유출이나 이런 것들이 취약했다고 한다. 그래서 POST 방법으로 로그인과 같은 민감한 정보들을 보안할 수 있도록 되었다.

 

아무튼 이를 방지하기 위해서 GET으로 민감한 정보를 보낼 수 있는 토큰을 얻낸 후, 민감한 정보를 보낼 때, POST 방식으로 토큰과 같이 보내면 정보를 응답해주는 방식으로 현재 쓰이고 있다.

 

만약 토큰 없이 POST를 보내게 된다면 403에러를 반환받게 된다.

 

Django CSRF 구현

우선 setting.py 에서 MIDDLEWARE 리스트에 CSRF 미들웨어가 등록되어 있는지 확인해보자.

 

 

간단한 HTML을 작성하여 CSRF를 테스트 해보자.

 

 

<!DOCTYPE html>
<html lang="ko">
<head>
    <meta charset="UTF-8">
    <title>Test</title>
</head>
<body>
    {% block content %}
    <form action="" method="post">
    {% csrf_token %}
    title : <input type="text" name="title"><br>
    body : <input type="text" name="body"><br>
    
    <input type="submit" value="확인">
    {% endblock %}
</body>
</html>

 

간단히 제목과 내용을 적을 수 있는 HTML을 만들었다.

 

이제 여기서 확인을 눌렀을 때 POST로 보낼지 GET으로 보낼지 결정하는 것이 HTML에 form 태그이다.

form 태그에 method를 확인해보면 POST로 되어있다. 즉 버튼을 누르면 POST로 보내진다는 것이다.

 

그렇다고 저 페이지에 들어갈 때도 POST는 아니다. GET으로 요청받아 HTML페이지를 열고 버튼을 눌렀을 때 POST로 요청한다.

 

이제 위에서 설명한 것들을 함수로 구현해보자.

if 문은 POST로 요청이 들어왔을 때 처리하는 것이다. TestForm 이라는 객체를 forms.py에 선언하였다.

forms.py에 생성한 TestForm의 클래스다. 유의해서 볼 점은 기존 Test 테이블의 컬럼 자료형과 같게 만들었다는 것과 label을 지정 했다는 것이다. 이 label은 html에서 name 속성에 해당하는 것들이다. 즉 해당 name의 자료를 TestForm에 맞춰 넣는다는 것이다.

 

그리고 TestForm이 정상적으로 생성되었다면 그 내용들을 QuerySet을 통해 create하게 된다. 그리고 마지막으로 redirect 함수를 통해 다음에 연결된 페이지로 넘어가게 된다.

 

redirect는 Model 객체에서 get_absolute_url을 호출하게된다.

이 때, get_absolute_url 에는 POST를 다 처리한 후 넘어갈 페이지 url을 반환한다.

이 반환하는 url도 get_absolute_url를 오버라이딩하여 지정할 수 있다.

아래 코드를 확인 해보자.

 

 

get_absolute_url이라는 함수가 또 reverse라는 함수를 반환하는데 첫번째 인자로 들어가있는 주소를 출력하게 된다.

하지만 reverse는 보통 방법으로는 Path 변수가 있는 url을 반환할 수 없다. 그래서 Path 변수를 사용하는 url은 다음과 같이 변경 해야한다.

 

func5와 func6은 둘 다 Path 변수를 사용하는 url이다. 하지만 reverse로 해당 url을 부르기 위해서는 name인자를 설정해 주어야 한다. name 인자에 넣은 문자열을 통해 reverse로 url을 불러올 수 있다.

 

reverse의 args 또는 kwargs를 통해 인자를 전달하면 Path 변수를 사용한 url을 반환한다.

 

 

else문은 POST가 아닌 요청이 들어왔을 때, 위에서 작성한 HTML을 요청하여 브라우저에 출력한다.

 

결과는 다음과 같다.

 

'Python > Django' 카테고리의 다른 글

[Django] Django File - Static File  (0) 2022.11.19
[Django] 기본 View 와 Generic View  (0) 2022.11.19
[Django] Manager & QuerySet  (0) 2022.11.16
[Django] 모델 관계 설정  (0) 2022.11.15
[Django] Template  (0) 2022.11.15