본문 바로가기
IT

Chap 2. 장고 기본 요소 학습#10 (질문 등록 기능 만들기)

by 밤고래 2021. 6. 19.
반응형

 

안녕하세요. 밤고래에요 :)

오늘은 기존에 질문 리스트, 답변 등록 게시판 기능이 구현된 pybo 웹사이트에 질문 등록 기능을 만들 예정입니다.

 

2-10 질문 등록 기능 만들기

지금까지는 질문을 등록하기 위해 장고 셸이나 장고 Admin을 사용했다.

이번에는 파이보 서비스를 통해 질문을 등록하는 기능을 만들어 보자.

 

 

[실습] 질문 등록 기능 만들기(p109)

질문 목록 화면 아래에 질문 등록 버튼을 만든 다음, 질문 등록 기능을 완성해보자.

현재는 아래와 같이 질문 목록 화면 아래에 별도의 버튼이 없는 상태이다.

 

 

Step 1. 질문 등록 버튼 만들기

question_list.html 템플릿의 </table> 태그 아래에 버튼을 추가하자.

 

 

a 엘리먼트에 href 속성으로 질문 등록 URL 을 추가하고, 부트스트랩 클래스 btn btn-primary 를 지정했다.

 

 

Step 2. URL 매핑 추가를 위해 pybo/urls.py 수정하기

1단계에서 {% url 'pybo:question_create' %} 이 추가되었으니 pybo/urls.py 파일에 URL 매핑을 추가하자.

 

 

 

Step 3. pybo/views.py 수정하기

2단계에서 URL 매핑에 의해 실행될 views.question_create 함수를 추가하자

플로우를 다시 되짚어보자면, 맨 먼저 url.py 에 정의된 url 로 접속되고

해당 url 과 매핑되어있는 views 파일의 어떠한 함수를 실행하도록 한다. 

이번에는 create URL 을 생성하였으므로 views 파일 내에 create 역할을 실제로 하는 함수를 정의한다.

정의 부분에는 템플릿을 보여주는(rendering) 것을 Return 한다.

 

Flow : URL -> Function -> Template(.html)

 

 

quesiton_create 함수는 QuestionForm 클래스로 생성한 객체 form 을 사용할 것이다.

여기서 QuestionForm 클래스는 질문을 등록하기 위해 사용하는 장고의 폼이다.

render 함수에 전달한 {'form': form} 은 템플릿에서 폼 엘리먼트를 생성할 때 사용한다.

 

 

Step 4. pybo/forms.py에 장고 폼 작성하기

pybo 디렉터리 바로 아래에 forms.py 파일을 새로 만들어 ModelForm을 상속받은 QuestionForm 클래스를 작성하자.

 

 

 

이 같은 클래스를 장고 폼이라 한다.

장고 폼은 사실 2개의 폼으로 구분할 수 있는데,

forms.Form을 상속받으면 , forms.ModelForm을 상속받으면 모델 폼이라 부른다.

여기서는 forms.ModelForm을 상속받아 모델 폼을 만들었다.

 

모델 폼은 말 그대로 모델(ex-Question, Answer)과 연결된 폼이며,

모델 폼 객체를 저장하면 연결된 모델의 데이터를 저장할 수 있다.

 

장고 모델 폼은 내부 클래스로 Meta 클래스를 반드시 가져야 하며,

Meta 클래스에는 모델 폼이 사용할 모델과 모델의 필드를 적어야 한다.

 

QuestionForm 클래스는 Question 모델과 연결되어 있으며, 필드로 subject, content 를 사용한다고 정의했다.

 

 

Step 5. pybo/question_form.html 만들어 장고 폼 사용하기

질문 등록을 위해 pybo/question_form.html 파일을 생성하고 다음과 같이 작성하자.

 

 

 

코드의 {{ form.as_p }} 에서 form 이 바로 question_create 함수에서 전달한 QuestionForm 객체이다.

여기서 {{ form.as_p }} 는 모델 폼과 연결된 입력 항목을 subject, content에 값을 입력할 수 있는 HTML 코드를 자동으로 만들어 준다.

 

 

Step 6. 질문 등록 화면 확인하기

서버를 구동하고, /pybo/ 페이지를 요청해서 지금까지 구현한 기능을 확인해보자!

질문 리스트 페이지 왼쪽 하단에 '질문 등록하기' 버튼이 생성되었다.

 

 

 

질문 등록하기 버튼을 누르면, 이번에 새로 생성한 질문 등록 페이지가 나오며, 

템플릿에 작성한 {{ form.as_p }} 에 의해 나타난 입력 항목 subject, content 를 확인할 수 있다.

 

 

 

 

그런데 내용을 입력하고 저장하기 버튼을 누르면 아무 반응이 없다.

왜냐라면 pybo/views.py 파일에 정의한 question_create 함수에 입력데이터를 저장하기 위한 코드를 작성하지 않았기 떄문이다.

 

 

Step 7. 입력 데이터 저장하기

pybo/views.py 파일의 question_create 함수를 수정하자.

 

 

 

URL 요청을 POST 와 GET 요청방식에 따라 다르게 처리하였다. 

질문 목록 화면(question_list.html) 에서 <질문 등록하기> 버튼을 누르면

/pybo/quesiton/create/가 GET 방식으로 요청되어 질문 등록 화면이 나타나고, 

질문 등록 화면에서 입력 값을 채우고 <저장하기> 버튼을 누르면

/pybo/quesiton/create/가 POST 방식으로 요청되어 데이터가 저장된다.

 

그리고 QuesitonForm 객체도 GET 방식과 POST 방식일 경우 다르게 생성하였다.

form.is_valid 함수는 POST 요청으로 받은 form 이 유효한지 검사한다.

폼이 유효하지 않다면 폼에 오류가 저장되어 화면에 전달될 것이다.

 

그리고 question = form.save(commit=False)는 form 으로 Question 모델 데이터를 저장하기 위한 코드이다.

여기서 commit=False 는 임시 저장을 의미한다. 

즉, 실제 데이터는 아직 저장되지 않은 상태를 말한다.

이렇게 임시 저장을 사용하는 이유는 폼으로 질문 데이터를 저장할 경우 Question 모델의 create_date 에 값이 설정되지 않아 오류가 발생하기 때문이다(폼에는 현재 subject, content 필드만 있고, create_date 필드는 없다)

 

 

Step 8. 질문 등록 기능 확인하기

제목과 내용 입력후 저장하기를 누르면, 정상적으로 DB 에 입력되어 질문 리스트 페이지에서 조회된다.

 

 

 

 

Step 9. 폼에 부트스트랩 적용하기

{{ form.as_p }} 태그는 우리가 직접 생성한 것이 아닌, 사전 정의되어있는 기본 form 이다.

form 엘리먼트와 입력 항목을 자동으로 생성해주므로 편리하기는 하지만 부트스트랩을 적용할 수 없다는 단점이 있다.

그러나 완벽하지는 않지만, QuestionForm 클래스 내부에 있는 Meta 클래스에 widgets 속성을 추가하면 적용이 가능하다.

 

 

위 코드를 적용해보면 아래와 같이 질문 등록 화면에 부트스트랩이 적용된 화면을 볼 수 있다. 

 

 

 

Step 10. label 속성 수정하여 Subject, Content 한글로 변경하기

 

 

Step 11. 수작업으로 폼 작성하기

{{ form.as_p }} 를 사용하면 빠르게 템플릿을 만들 수 있지만 HTML 코드가 자동으로 생성되므로 디자인 측면에서 많은 제한이 생기게 된다. 

기본 form 인 {{ form.as_p }} 를 삭제하고 새로 폼을 작성해보자.

 

 

 

제목의 value에는 value="{{ form.subject.value|default_if_none:'' }}을 대입했는데, 이는 오류 발생시 기존 입력값을 유지하가 위함이다.

 

 

 

 

[실습] 답변 등록 기능에 장고 폼 적용하기(p119)

Step 1. AnswerForm 클래스 추가하고 answer_create 함수 수정하기

질문 등록 기능에 장고 폼을 적용한 것처럼 답변 등록 기능에도 장고 폼을 적용하자.

답변을 등록할 때 사용할 AnswerForm 클래스를 pybo/forms.py 파일에 다음과 같이 작성하자.

 

 

그런 다음 pybo/views.py 파일의 answer_create 함수를 수정하자.

answer_create 함수는 question_create 함수와 거의 동일하다.

 

 

Step 2. 질문 상세 템플릿에 오류 표시 영역 추가하기

 

 

 

이렇게 수정하고 답변 내용 없이 답변을 등록하려고 하면 오류 메시지가 아래처럼 나온다. 

 

 

 

 

 

여기까지 질문 등록 기능 만들기를 구현하였습니다 :) 

감사합니다.

반응형

댓글