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 |