Study/django

django - Questionform

1. 질문등록 버튼생성 - 질문등록 버튼은 question_list.html에 있어야한다.

{% extends 'base.html' %}
{% block content %}
<div class = "container my-3">
  <table class="table">
	<!-- 생략 -->
  </table>
  <a href="{% url 'pybo:question_create' %}" class="btn btn-primary">
    질문 등록하기
  </a>
</div>
{% endblock %}

 

2. URL 매핑 pybo/urls.py 질문등록 - question/create/ 경로를 views.py에 question_create 함수에 넘김.

from django.urls import path
from . import views

app_name = 'pybo'

urlpatterns = [
    path('', views.index, name='index'),
    path('<int:question_id>/', views.detail, name='detail'),
    path('answer/create/<int:question_id>/', views.answer_create, name='answer_create'),
    path('question/create/', views.question_create, name='question_create'),
]

 

3. views.py 수정 - 질문내용을 Database에 저장하고 question_form.html을 리프레시한다.

from .forms import QuestionForm, AnswerForm

/*--- 생략 ---*/

def question_create(request):
    """
    pybo 질문 등록
    """
    if request.method =='POST':

        form = QuestionForm(request.POST)

        if form.is_valid():
            question = form.save(commit=False)
            question.create_date = timezone.now()
            question.save()
            return redirect('pybo:index')

    else:
        form = QuestionForm()

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

QuestForm 객체가 GET방식과 POST 방식일 경우 다르게 생성한것을 알 수 있다. 
GET의 경우는 QuestForm()과 같이 argument가 없고 POST의 경우는 Question(request.POST) 와 같이 화면에서 전달받은 데이터로 폼의 값이 채워지도록 객체를 생성했다. form.is_valid 함수는 POST 요청으로 받은 form 이 유효한지 검사한뒤 폼이 유효하지 않다면 폼에 오류가 저장되어 화면에 전달하는 역할을 한다.

question = form.save(commit=False)는 form 으로 Question 모델 데이터를 저장하기 위한 코드이다.
여기서 commit=False는 임시저장을 의미한다. 폼으로 질문데이터를 저장할 경우 create_date에 값이 설정되지 않아 오류가 발생하기 때문에 임시 저장후에 question객체를 반환받아서 create_date에 값을 설정한후 question.save()로 실제 저장을 한다.

더보기

GET은 클라이언트에서 서버로 정보를 요청하기 위해 사용되는 메서드이다. 게시판의 게시물을 조회할때 쓴다. GET을 통한 요청은 URL 주소 끝에 파라미터로 포함되어 전송된다. 이 부분을 쿼리 스트링 (query string) 이라고 부른다. POST는 클라이언트에서 서버에 리소스를 생성하거나 업데이트하기 위해 사용하는 메서드이다. 게시판의 게시글을 작성할 때 사용된다. POST는 HTTP 메시지 BODY 부분에 담아서 서버에 전달한다. POST로 데이터를 전송할때는 용량이 큰 데이터를 보낼때 혹은 보안이 필요할때 사용한다. 하지만 POST도 결국 데이터가 암호화 되어 있지 않으면 외부에서 볼수는 있다. 

  • GET은 브라우저 히스토리에 남는다.
  • GET은 북마크될 수 있다.
  • GET 요청은 브라우저 마다 길이제한이 있다.
  • GET은 파라미터가 직접노출되므로 최소한의 보안도 지킬수 없다.
  • GET은 일반적으로 데이터를 조회할때만 사용한다.
  • POST는 캐시되지 않는다
  • POST요청은 브라우저 히스토리에 남지 않는다
  • POST요청은 북마크되지 않는다
  • POST요청은 데이터길이에 제한이 없다.

 

4. forms.py 작성

from django import forms
from django.forms import widgets
from pybo.models import Question, Answer

class QuestionForm(forms.ModelForm):
    # 장고의 모델폼은 내부 클래스로 Meta클래스를 반드시 가져야 한다.
    # Meta 클래스에는 모델 폼이 사용할 모델명과 필드명을 적어야한다. 
    class Meta:
        model = Question
        fields = ['subject', 'content']
        # {{form.as_p}}를 사용하면 빠르게 템플릿을 만들 수 있지만 
        # HTML 코드가 자동으로 생성되므로 디자인측면에서 제한이 생긴다. 
        # 또한 디자인영역과 서버프로그래밍 영역이 혼재되어 
        # 개발 역할을 분리하기도 애매해진다.
        # {{form.as_p}}를 사용할 경우 아래와 같이 class를 적용 할 수 있다.
        # widgets = {
        #     'subject': forms.TextInput(attrs={'class':'form-control'}),
        #     'content': forms.Textarea(attrs={'class':'form-control', 'rows':10}),
        # }
        labels = {
            'subject': '제목',
            'content': '내용',
        }


class AnswerForm(forms.ModelForm):
    class Meta:
        model = Answer
        fields = ['content']
        labels = {
            'content': '답변내용',
        }

 

 

5. question_form.html 작성

{% extends 'base.html' %}

{% block content %}
<div class="container">
    <h5 class="my-3 border-bottom pb-2">질문 등록</h5>
    <form method="POST" class="post-form my-3">
        {% csrf_token %}
        <!-- 오류표시 start -->
        {% if form.errors %}
            <div class="alert alert-danger" role="alert">
            {% for field in form %}
                {% if field.errors %}
                <strong>{{ field.label }}</strong>
                {{ field.errors }}
                {% endif %}
            {% endfor %}
            </div>
        {% endif %}
        <!-- 오류표시 End -->
        <div class="form-group">
            <label for="subject">제목</label>
            <input type="text" class="form-control" name="subject" id="subject" 
                   value="{{ form.subject.value|default_if_none:'' }}">
        </div>
        <div class="form-group">
            <label for="content">내용</label>
            <textarea class="form-control" name="content" id="content" row="10">
                      {{ form.content.value|default_if_none:'' }}
            </textarea>
        </div>
        <!--사용하지 않음. {{ form.as_p }} -->
        <button type="submit" class="btn btn-primary">저장하기</button>
    </form>
</div>

{% endblock %}

'Study > django' 카테고리의 다른 글

django - StandardHTML  (0) 2021.09.26
django - CSS  (0) 2021.09.25
django - Answerform  (0) 2021.09.25
django - Namespace  (0) 2021.09.25
django - QuestionContent  (0) 2021.09.25