17.Django(장고) - ecommerce 프로젝트 - 게시판 글등록-폼 적용

JungSik Heo·2024년 12월 5일

URL 1.매핑

boards\urls.py

(... 생략 ...)
urlpatterns = [
    (... 생략 ...)
   path('post/create/', views.post_create, name='post_create'),
]

views.question_create 함수를 호출하도록 매핑

2.게시판 글등록을 위한 버튼 추가

templates\boards\post_list.html
버튼 생성해 보기

    (... 생략 ...)
    </table>
    <a href="{% url 'boards:post_create' %}" class="btn btn-primary">글 등록하기</a> 
</div>
{% endblock %}

3.폼(Form)

흐름에 따라 이제 views.question_create 함수를 작성해야 한다. 하지만 뷰 함수를 작성하기 전에 폼(Form)에 대해서 먼저 알아보자. 폼은 쉽게 말해 페이지 요청시 전달되는 파라미터들을 쉽게 관리하기 위해 사용하는 클래스이다. 폼은 필수 파라미터의 값이 누락되지 않았는지, 파라미터의 형식은 적절한지 등을 검증할 목적으로 사용한다. 이 외에도 HTML을 자동으로 생성하거나 폼에 연결된 모델을 이용하여 데이터를 저장하는 기능도 있다.

form에 대하여 좀더 이해를 해보자

✏️장고에게 form이란?

폼의 기능

  • 렌더링을 위해 데이터를 준비하고 재구상한다
  • HTML폼을 만들어준다
  • 클라이언트로부터 제출된 데이터를 받고 처리해준다

✏️한 문장으로?
Model 객체를 가져다가 좀 더 쉽게 화면을 구성할 수 있게 도와주는 녀석(?)

forms.py 작성

boards\forms.py

from django import forms
from boards.models import Post

class PostForm(forms.ModelForm):
    class Meta:
        model = Post  # 사용할 모델
        fields = ['title', 'content'] 

PostForm 모델 폼(forms.ModelForm)을 상속했다. 장고의 폼은 일반 폼(forms.Form)과 모델 폼(forms.ModelForm)이 있는데 모델 폼은 모델(Model)과 연결된 폼으로 폼을 저장하면 연결된 모델의 데이터를 저장할수 있는 폼이다. 모델 폼은 이너 클래스인 Meta 클래스가 반드시 필요하다. Meta 클래스에는 사용할 모델과 모델의 속성을 적어야 한다.

즉, PostForm Post 모델과 연결된 폼이고 속성으로 Question 모델의 subject와 content를 사용한다고 정의한 것이다.

뷰 함수

그리고 다시 흐름으로 돌아와 views.post_create 함수를 다음과 같이 작성하자.

boards\views.py

def post_create(request):
    form = PostForm()
    return render(request, 'boards/post_form.html', {'form': form})

템플릿

templates\boards\post_form.html

{% extends 'boards/base.html' %}
{% block content %}
  <div class="container">
    <h5 class="my-3 border-bottom pb-2">질문등록</h5>
    <form method="post">
      {% csrf_token %}
      {{ form.as_p }}
      <button type="submit" class="btn btn-primary">저장하기</button>
    </form>
  </div>
{% endblock %}

form.as_p 에 대한 이해

(form.as_p는 폼의 각 필드를 p 태그 안에서 레이블과 텍스트로 배치한다). 폼을 랜더링하는 옵션으로 form, form.as_p, form.as_table, form.as_ul 등이 있는데, 이 옵션은 각 필드를 어떤 HTML 태그로 Wrapping 할 것인가를 지정

템플릿에서 사용한 {{ form.as_p }}의 form은 post_create 함수에서 전달한 PostForm의 객체이다. {{ form.as_p }}는 폼에 정의한 title, content 속성에 해당하는 HTML 코드를 자동으로 생성한다.

잠깐, 다음으로 진행하기 전에 한 가지 눈여겨 보아야 할 부분이 있다. 그것은 바로

처럼 form 태그에 action 속성을 지정하지 않았다는 점이다. 보통 form 태그에는 항상 action 속성을 지정하여 submit 실행시 action에 정의된 URL로 폼을 전송해야 한다. 하지만 여기서는 특별하게 action 속성을 지정하지 않았다. form 태그에 action 속성을 지정하지 않으면 현재 페이지의 URL이 디폴트 action으로 설정된다.

이제 제목 와 content 입력 창에 아무 값이나 입력하고 "저장하기" 버튼을 클릭해 보자. 하지만 아무런 반응이 없을 것이다. 왜냐하면 post_create 함수에 데이터를 저장하는 코드를 아직 작성하지 않았기 때문이다.

다음처럼 post_create 함수를 수정하자.

def post_create(request):

    if request.method == 'POST':
        form = PostForm(request.POST)
        
        if form.is_valid(): # 폼이 유효하다면
            post = form.save(commit=False) # 임시 저장하여 post 객체를 리턴받는다.
            #post.created_at = timezone.now()# 실제 저장을 위해 작성일시를 설정한다.
            post.save()# 데이터를 실제로 저장한다.
            return redirect('boards:index')
    else:
        form = PostForm()

    context = {'form': form}
    return render(request, 'boards/post_form.html', context)  

코드 설명

GET 방식에서는 form = PostForm() 처럼 PostForm 인수 없이 생성했지만 POST 방식에서는 form = PostForm(request.POST) 처럼 request.POST를 인수로 생성했다. request.POST를 인수로 QuestionForm을 생성할 경우에는 request.POST에 담긴 subject, content 값이 QuestionForm의 subject, content 속성에 자동으로 저장되어 객체가 생성된다.

request.POST에는 화면에서 사용자가 입력한 내용들이 담겨있다.

그리고 form.is_valid()는 form이 유효한지를 검사한다. 만약 form에 저장된 subject, content의 값이 올바르지 않다면 form에는 오류 메시지가 저장되고 form.is_valid()가 실패하여 다시 질문 등록 화면을 렌더링 할 것이다.

이 때 form에는 오류 메시지가 저장되므로 화면에 오류를 표시할 수 있다.

form이 유효하다면 if form.is_valid(): 이후의 문장이 수행되어 질문 데이터가 생성된다. question = form.save(commit=False)는 form에 저장된 데이터로 Post 데이터를 저장하기 위한 코드이다. PostForm이 Question 모델과 연결된 모델 폼이기 때문에 이와 같이 사용할 수 있다. 여기서 commit=False는 임시 저장을 의미한다. 즉, 실제 데이터는 아직 데이터베이스에 저장되지 않은 상태를 말한다. 여기서 form.save(commit=False) 대신 form.save()를 수행하면 왜냐하면 question.save()로 실제 데이터를 저장하는 것이다.

설명이 무척 길었지만 여기서 설명한 내용을 꼭 숙지하기 바란다. 왜냐하면 우리가 앞으로 만들 기능들이 모두 이와 비슷한 패턴을 따르기 때문이다.

폼 위젯

https://devspoon.tistory.com/10

profile
쿵스보이(얼짱뮤지션)

0개의 댓글