django | 14. CREATE(ModelForm 버전 추가)

sojung·2021년 6월 17일
0

django

목록 보기
15/21
post-thumbnail

질문 등록 페이지 생성하고 연결하기

1. 질문 등록 페이지 만들기

<!-- home/question_form.html -->

<h1>질문 등록 페이지</h1>

2. 질문 등록 버튼 만들기

<!-- home/question_list.html -->

...

<a href="{% url 'home:question_create' %}">질문 등록하기</a>

버튼을 누르면 home앱의 question_create라는 경로로 이동한다. (아직 안 만듦)

3. urls.py에 경로 만들기

# home/urls.py
	
urlpatterns = [
  ...
  path('question_create', question_create, name="question_create"),
]

question_cerate라는 함수를 실행한다. (아직 안 만듦)

4. views.py에 함수 만들기

# home/views.py

...

def question_create(request):
  return render(request, 'home/question_form.html')

페이지를 새로 만들어 연결까지 해 주었다.

모델폼 이용하기

1. forms.py에 장고 폼 작성하기

# home/forms.py

from django import forms
from home.models import Question

class QuestionForm(forms.ModelForm): # 모델 폼을 상속받은 QuestionForm 클래스
  class Meta: # 내부 Meta 클래스
    model = Question
    fields = ['subject', 'content']

위와 같은 클래스를 장고 폼이라고 한다. 장고 폼은 2개의 폼으로 구분할 수 있는데, forms.Form을 상속받으면 폼이라고 하고, forms.ModelForm을 상속받으면 모델 폼이라고 한다.
현재는 모델 폼을 만들었고, 모델 폼은 말 그대로 모델과 연결한 폼이며, 모델 폼 객체를 저장하면 연결된 모델의 데이터를 저장할 수 있다.
장고 모델 폼은 내부 클래스로 Meta 클래스를 반드시 가져야 하며, Meta 클래스에는 모델 폼이 사용할 모델과 모델의 필드들을 적어야 한다.
QuestionForm 클래스는 Qeustion 모델과 연결되어 있으며, 필드로 subject와 content를 사용한다고 정의하였다.

2. views.py 함수 수정하기

# home/views.py

...
from .forms import QuestionForm # QuestionForm 클래스 import 하기

...

def question_create(request):
  a_form = QuestionForm() # QuestionForm 클래스로 생성한 객체 a_form을 사용할 것이다.
  context = {'form' : a_form }
  return render(request, 'home/question_form.html', context)

3. 질문 등록 페이지 수정하기

<!-- home/question_form.html -->

{% extends 'base.html' %}
{% block content %}

<div>
  <h5>질문 등록</h5>
  <form method="POST">
    {% csrf_token %}
    {{ form.as_p }}
    <!-- form이 views.py > question_create 함수에서 전달한 QuestionForm 객체이다. -->
    <!-- {{ form.as_p }} 이 코드는 모델 폼과 연결된 입력 항목 subject, content에 값을 입력할 수 있는 HTML 코드를 자동으로 만들어 준다. -->
    <button>저장하기</button>
  </form>
</div>

{% endblock %}

4. 입력 데이터 저장하기 > views.py 수정하기

# home/views.py

...

def question_create(request):
  if request.method == 'POST':
    a_form = QuestionForm(request.POST)
    if a_form.is_valid():
      question = a_form.save(commit=False) # 폼에 없는 필드인 create_date부분을 자동입력으로 모델을 설정하였기 때문에 a_form.save()라고 작성하여도 오류가 발생하지는 않는다.
      question.save()
      return redirect('home:question_list')
  else: # request.method == 'GET'인 경우
    a_form = QuestionForm() # QuestionForm 클래스로 생성한 객체 a_form을 사용할 것이다.
  context = {'form' : a_form }
  return render(request, 'home/question_form.html', context)
  • 질문 등록하기 버튼을 누르면 GET 방식으로 질문 등록 화면이 나타나고, 저장하기 버튼을 누르면 POST 방식으로 요청되어 데이터가 저장된다.
  • QuestionForm 객체가 GET 방식의 경우, QuestionForm()과 같이 입력값 없이 객체를 생성했고, POST 방식의 경우에는 QuestionForm(request.POST)처럼 화면에서 전달받은 데이터로 폼의 값이 채워지도록 객체를 생성했다.
  • a_form.is_valid 함수는 POST 요청으로 받은 a_form이 유효한지 검사한다. 폼이 유효하지 않다면 폼에 오류가 저장되어 화면에 전달될 것이다.
  • question = a_form.save(commit=False)는 form으로 Question 모델 데이터를 저장하기 위한 코드이다. 여기서 commit=False는 임시 저장을 의미한다. 즉, 실제 데이터는 아직 저장되지 않은 상태를 말한다. 이렇게 임시 저장을 사용하는 이유는 폼으로 질문 데이터를 저장할 경우 Question 모델의 create_date에 값이 설정되지 않아 오류가 발생하기 때문이다. (폼에는 현재 subject, content 필드만 있고 create_date 필드는 없다) 이러한 이유로 임시 저장을 한 question 객체를 반환받아 create_date에 값을 설정한 후 question_save()로 실제 저장하는 것이다.
  • question = a_form.save()를 수행하면 create_date 속성값이 없다는 오류 메시지가 나타난다.
    -> create_date 부분을 현재 자동 입력으로 모델을 설정하여서 이 블로그를 따라왔다면 오류가 발생하지 않는다. models.py에서 create_date = models.DateTimeField()라고 작성하였다면 오류가 발생한다.


잘 생성된다.

폼 꾸미기

1. label 사용하여 한글로 변경하기

# home/forms.py

...

class QuestionForm(forms.ModelForm): # 모델 폼을 상속받은 QuestionForm 클래스
  class Meta: # 내부 Meta 클래스
    model = Question
    fields = ['subject', 'content']
    # labels 코드 추가하기
    labels = {
      'subject' : '제목',
      'content' : '내용',
    }

모델폼 이용하지 않고 CREATE 구현하기

모델폼을 이용하지 않고 create를 구현하기 위한 로직은 다음과 같다.
1. 글 작성하기 버튼을 클릭하면 -> question_new.html로 이동
2. 글을 작성하고 작성완료 버튼을 클릭하면 -> question_create 함수가 실행되어 글 작성을 완료한다.

작성 페이지 만들기

html 파일 만들기

<!-- question_new.html -->

{% extends 'base.html' %}
{% block content %}

<h1>질문 등록</h1>
<form action="#" method="POST" enctype="multipart/form-data">
  {% csrf_token %}
  <div>
    <label>글 제목</label>
    <input type="text" name="subject">
  </div>

  <div>
    <label>글 내용</label>
    <textarea name="content"></textarea>
  </div>

  <input type="submit" value="글 작성">
</form>

{% endblock %}

일단 form태그의 action 메소드는 빈칸으로 둔다. 글 작성 버튼을 누르면 action이 실행되어 create가 완료되게 할 것이다.

views.py에서 함수 만들기

# views.py

def question_new(request):
  return render(request, 'home/question_new.html')

urls.py에서 url 연결하기

# urls.py

...
  path('question_new', question_new, name="question_new"), # 작성 페이지로 이동

페이지 연결까지 완료하였다.

버튼 연결하기

<!-- question_list.html -->

...

<a href="{% url 'home:question_new' %}">질문 등록하기</a>

질문 등록하기 버튼을 누르면 question_new라는 이름을 가진 url이 실행된다.

create 함수 작성하기

def question_create(request):
  if request.method == "POST":
    subject=request.POST.get('subject') # HTML의 name에서 받아온 값을 subject에 담는다.
    content=request.POST.get('content')
    Question.objects.create(subject=subject, content=content)
  return redirect('home:question_list')

form의 action에 create함수 연결하기

<!-- question_new.html -->

{% extends 'base.html' %}
{% block content %}

<h1>질문 등록</h1>
<form action="{% url 'home:question_create' %}" method="POST" enctype="multipart/form-data">
  {% csrf_token %}
  <div>
    <label>글 제목</label>
    <input type="text" name="subject">
  </div>

  <div>
    <label>글 내용</label>
    <textarea name="content"></textarea>
  </div>

  <input type="submit" value="글 작성">
</form>

{% endblock %}

글 작성 버튼을 누르면 form의 action이 실행된다. home앱의 question_create라는 이름을 가진 함수가 실행된다.

profile
걸음마코더

0개의 댓글