🥞 BE
home

8. Form

입력공간을 자동으로 생성해주는 Form에 대해 알아보자.

form의 종류

model을 기반으로 한 form
지금까지는 제목과 날짜, 본문을 입력하고 model 객체를 생성해 데이터를 집어넣어 저장했다. 그러나 form을 이용하면 model 맞춤형 form을 구성해주고, 보다 편리하게 저장도 할 수 있다.
임의의 입력공간을 위한 form
굳이 model을 이용하지 않고 임의로 form을 구성하는 것도 가능하다.

forms.py 작성

이제 form을 이용해 게시글 등록 부분을 변경해보자.
기반으로 하고싶은 models.py 파일과 동일한 경로에 forms.py 파일을 생성해준다.
forms.py 파일은 view.py 파일에 임포트해서 사용하는 파일일 뿐이다. form 관련 코드들을 직접 view에 작성해줘도 괜찮지만 효율적인 코드관리를 위해 파일을 나눠주었다.
필요한 클래스를 import하고 클래스를 정의한다.
from django import forms from .models import Blog class BlogPost(forms.ModelForm): class Meta: model = Blog fields = ['title', 'body']
Python
복사
blog\forms.py
모델을 기반으로 하는 클래스를 제작해야 하니 form 클래스의 ModelForm을 인자로 넘겨준다.
다음 메타클래스를 선언하고, 그 안에 model과 fields를 정의해보자. 어떤 모델을 기반으로 Form을 생성할지 model에 작성한다. 그리고 모델의 속성들 중 입력받길 원하는 속성(title, body)fields에 작성한다. 날짜는 사용자가 직접 입력하지 않아도 views.py에서 집어넣게 구현해보자.

urls.py 수정

path('newblog/', views.blogpost, name='newblog'),
Python
복사
blog\urls.py
127.0.0.1:8000/blog/newblog 로 접속하게 되면 blogpost 함수가 실행되게끔 path를 추가해준다.

views.py 수정

먼저 forms.py의 BlogPost 클래스를 import 해준다.
from .forms import BlogPost
Python
복사
입력할 수 있는 form을 사용자에게 보여주고, 입력된 form의 값을 처리할 함수가 필요하다.
def blogpost(request): if request.method == 'POST': # POST방식으로 요청이 들어왔을 때 실행할 코드 - form에 입력받은 데이터를 저장하기 else: # GET방식으로 요청이 들어왔을 때 실행할 코드 - form을 보여주기
Python
복사
blogpost 함수는 request의 method 타입에 따라 다른 일을 수행한다.
GET 방식으로 요청이 들어오면 내가 만든 form을 html로 보여주고, POST 방식으로 요청이 들어오면 form으로 받은 데이터들을 저장하는 것이 목표.
def blogpost(request): if request.method == 'POST': form = BlogPost(request.POST) if form.is_valid(): post = form.save(commit=False) post.pub_date = timezone.now() post.save() return redirect('home') else: form = BlogPost() return render(request, 'blog/write.html', {'form': form})
Python
복사
POST 방식으로 요청이 들어온다면:
form에 BlogPost 객체를 만들고, 받아온 데이터를 넣어준다. is_valid() 함수는 form으로 입력받은 값들이 유효한지 판단 해주는 함수이다. 만약 유효하다면 post = form.save(commit=false)로 form에 입력된 데이터들을 가져온다. save 함수는 저장하는 함수이지만, 인자에 commit=False 를 입력해주면 저장하지 않고 form 데이터만 가져올 수 있다. 자동으로 현재 시간이 들어가도록 post.pub_date = timezone.now() 구문을 작성해줬으면, save 구문으로 진짜 저장한다.
GET 방식으로 요청이 들어온다면:
BlogPost 클래스의 객체를 만들어 변수에 넣어준다. 이후 html을 띄울 때 딕셔너리 자료형으로 넣어 전달.

template 수정

{% extends 'base.html' %} {% block content %} <br> <div class='container'> <form method='POST'> {% csrf_token %} <table> {{form.as_table}} </table> <br> <input class="btn btn-dark" type="submit" value="제출하기"> </form> </div> {% endblock %}
HTML
복사
blog/templates/blog/new.html
기존 write.html을 다음과 같이 수정해주어도 되고, 나는 new.html을 만들어 테스트용으로 사용했다.
table태그로 감싼 뒤 템플릿 태그를 통해 form을 출력한다.
as_table은 form을 table 형식으로 출력하겠다는 의미의 메소드이다. submit을 클릭하면 위에 작성했던 form이 views.py로 날아가 데이터를 처리한다.
html을 다 지웠는데도 다음과 같이 form이 출력된다. 테스트를 해보자.
코드의 진행 흐름을 보면 urls.py에서 blogpost 함수를 호출하고 있다. 함수를 보니 method에 따라 다른 일을 수행하고 있다. 그냥 화면을 보여주길 원했으니 GET방식일테고, form을 html로 보내주는 코드를 발견한다. 여기서 form은 form.py를 import 시켰기에 작동하며, forms.py를 보니 모델을 기반으로 form을 만들어주고 있는 것을 볼 수 있다.