장고:답변쓰기(댓글쓰기): 두 판 사이의 차이
보이기
| 39번째 줄: | 39번째 줄: | ||
class Answer(models.Model):#세부내용은 필요에 따라.. | class Answer(models.Model):#세부내용은 필요에 따라.. | ||
question = models.ForeignKey(Question, on_delete=models.CASCADE) | question = models.ForeignKey(Question, on_delete=models.CASCADE) | ||
content = models. | content = models.CharField(max_length=300) | ||
create_date = models.DateTimeField() | create_date = models.DateTimeField() | ||
</syntaxhighlight> | </syntaxhighlight> | ||
| 55번째 줄: | 55번째 줄: | ||
==답변 작성하기== | ==답변 작성하기== | ||
답변을 작성하는 기능의 view를 짜보자. | 답변을 작성하는 기능의 view를 짜보자. | ||
아무래도 form을 사용하지 않으면 유효성검사에 대한 처리를 따로 해주어야 한다. 모델을 저렇게 짜두어도 유효성검사를 해주진 않는다.(글자제한을 두어도 그냥 입력되어버린다.) | |||
{| class="wikitable" | {| class="wikitable" | ||
! | !과정 | ||
! | !코드 | ||
!폼을 사용하는 경우 | |||
|- | |||
|form작성 | |||
| | |||
|전체적으로.. | |||
글쓰기에서 글 작성과 유사하게 만들면 된다.<syntaxhighlight lang="python"> | |||
from django import forms | |||
from pybo.models import Answer | |||
class AnswerForm(forms.ModelForm): | |||
class Meta: | |||
model = Answer | |||
fields = ['content'] | |||
labels = { | |||
'content': '댓글내용', | |||
} | |||
</syntaxhighlight> | |||
|- | |- | ||
|template작성 | |template작성 | ||
|댓글 작성은 화면에서 이루어지므로, 탬플릿을 먼저 작성한다. | |댓글 작성은 화면에서 이루어지므로, 탬플릿을 먼저 작성한다. | ||
글쓰기의 상세조회 탬플릿에 다음의 코드를 추가한다.<syntaxhighlight lang="html"> | 글쓰기의 상세조회 탬플릿에 다음의 코드를 추가한다.<syntaxhighlight lang="html"> | ||
| 80번째 줄: | 100번째 줄: | ||
</div> | </div> | ||
</syntaxhighlight>글 detail 뷰에서 question객체를 탬플릿에 보냈는데, question 객체 안에 연결된 answer객체가 함께 담겨 딸려간다. | </syntaxhighlight>글 detail 뷰에서 question객체를 탬플릿에 보냈는데, question 객체 안에 연결된 answer객체가 함께 담겨 딸려간다. | ||
| | |좌측에서 등록을 위한 부분만 달리하면 된다.<syntaxhighlight lang="html"> | ||
<!--답변등록을 위한 것--> | |||
<form action="{% url '앱이름:answer_create' question.id %}" method="post"> | |||
{% csrf_token %} | |||
<!--폼에러를 나타내기 위한 것--> | |||
{% 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 %} | |||
<!--답변등록을 위한 칸--> | |||
{{ form.as_p }} | |||
<input type="submit" value="댓글등록"> | |||
</form> | |||
</syntaxhighlight> | |||
|- | |- | ||
|view 작성 | |view 작성 | ||
| 92번째 줄: | 131번째 줄: | ||
return redirect('앱이름:detail', question_id=question.id) | return redirect('앱이름:detail', question_id=question.id) | ||
</syntaxhighlight>question.answer_set은 question에 대한 모델임을 의미한다. foreign 키로 연결되어 있어 이처럼 사용 가능하다. | </syntaxhighlight>question.answer_set은 question에 대한 모델임을 의미한다. foreign 키로 연결되어 있어 이처럼 사용 가능하다. | ||
혹은 answer객체를 직접 불러와 내용을 저장할 수도 있다.<syntaxhighlight lang="python"> | 혹은 answer객체를 직접 불러와 내용을 저장할 수도 있다.<syntaxhighlight lang="python"> | ||
| 103번째 줄: | 143번째 줄: | ||
return redirect('앱이름:detail', question_id=question.id) | return redirect('앱이름:detail', question_id=question.id) | ||
</syntaxhighlight> | </syntaxhighlight> | ||
|<syntaxhighlight lang="python"> | |||
from django.shortcuts import render, get_object_or_404, redirect | |||
from .models import * #모델을 불러온다. | |||
from .forms import AnswerForm #answer폼을 불러온다. | |||
def answer_create(request, question_id): | |||
question = get_object_or_404(Question, pk=question_id) | |||
if request.method == "POST": | |||
form = AnswerForm(request.POST)#post를 통해 받은 폼. | |||
if form.is_valid(): | |||
answer = form.save(commit=False) | |||
answer.question = question #question객체 연결. | |||
answer.create_date = timezone.now() | |||
answer.save() | |||
return redirect('앱이름:detail', question_id=question.id) | |||
else: | |||
form = AnswerForm() | |||
context = {'question': question, 'form': form} | |||
return render(request, 'detail.html', context) | |||
#폼이 적절하지 않다면 에러메시지와 함께 detail로 보낸다. | |||
</syntaxhighlight> | |||
|- | |||
| | |||
| | |||
| | | | ||
|} | |} | ||
2020년 11월 2일 (월) 06:05 판
장고! 웹 프레임워크! 틀:장고
개요
글에 답변을 다는 기능이다. 댓글기능을 추가하는 거라 보면 좋겠다.
url 작성
urls.py 안에 필요한 기능을 다 담아주어야 한다.(뷰의 설정이나, import방식에 따라 뷰를 불러오는 방식이 달라질 수 있다.)
| 일반적으로 코드를 짜는 경우 | 제네릭 뷰를 사용하는 경우 |
|---|---|
다음과 같은 path를 추가해준다.
실제로 이동하는 링크는 아니지만, 기능을 구현하기 위한 것.from django.urls import path
from . views #해당 앱의 뷰를 불러온다.
app_name = 'pool'
urlpatterns = [
path('answer/create/<int:question_id>/', views.answer_create, name='answer_create'),
]
|
함수명을 바꾸어주어야 한다.
views.클래스뷰명.as_view()), 형태로. 클래스형 뷰임을 지정해주기 위해. |
#아직 함수를 짜주진 않았지만, 앞으로 만들 함수에 대해 연결해두자.
모델 작성
포함해야 할 것들이 있다. 작성자, 작성일자, 내용 등의 요소를 포함하여 모델을 작성한다. 이름은 answer로 하자.
/앱/models.py 안에 작성한다.
from django.contrib.auth.models import User
from django.db import models
class Answer(models.Model):#세부내용은 필요에 따라..
question = models.ForeignKey(Question, on_delete=models.CASCADE)
content = models.CharField(max_length=300)
create_date = models.DateTimeField()
관리자 기능에서 확인
모델이 제대로 작성되고, 글이 제대로 생성될 수 있는지 관리자기능에 등록한 후 answer를 작성해보자.
관리자 등록은 장고:관리자페이지 참조.
이상이 없으면 뷰 작성으로 넘어가자.
뷰, 탬플릿 작성
탬플릿과 연관이 깊으니, 같이 짜주자. 한 단계, 한 단계 차근차근 작동을 확인하며 넘어가자.
답변 작성하기
답변을 작성하는 기능의 view를 짜보자.
아무래도 form을 사용하지 않으면 유효성검사에 대한 처리를 따로 해주어야 한다. 모델을 저렇게 짜두어도 유효성검사를 해주진 않는다.(글자제한을 두어도 그냥 입력되어버린다.)
| 과정 | 코드 | 폼을 사용하는 경우 |
|---|---|---|
| form작성 | 전체적으로..
글쓰기에서 글 작성과 유사하게 만들면 된다.from django import forms
from pybo.models import Answer
class AnswerForm(forms.ModelForm):
class Meta:
model = Answer
fields = ['content']
labels = {
'content': '댓글내용',
}
| |
| template작성 | 댓글 작성은 화면에서 이루어지므로, 탬플릿을 먼저 작성한다.
<!--답변등록을 위한 것-->
<form action="{% url '앱이름:answer_create' question.id %}" method="post">
{% csrf_token %}
<textarea name="content" id="content" rows="15"></textarea>
<input type="submit" value="답변등록">
</form>
<!--답변을 보기 위한 것-->
<div>
<ul>
{% for answer in question.answer_set.all %}
<li>{{ answer.content }}</li>
{% endfor %}
</ul>
</div>
|
좌측에서 등록을 위한 부분만 달리하면 된다.<!--답변등록을 위한 것-->
<form action="{% url '앱이름:answer_create' question.id %}" method="post">
{% csrf_token %}
<!--폼에러를 나타내기 위한 것-->
{% 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 %}
<!--답변등록을 위한 칸-->
{{ form.as_p }}
<input type="submit" value="댓글등록">
</form>
|
| view 작성 | 작성 후에 다시 원 글로 이동이 필요하므로 redirect를 추가한다.from django.shortcuts import render, get_object_or_404, redirect
from .models import * #모델을 불러온다.
def answer_create(request, question_id):
question = get_object_or_404(Question, pk=question_id)
question.answer_set.create(content=request.POST.get('content'), create_date=timezone.now())
return redirect('앱이름:detail', question_id=question.id)
from django.shortcuts import render, get_object_or_404, redirect
from .models import * #모델을 불러온다.
def answer_create(request, question_id):
question = get_object_or_404(Question, pk=question_id)
answer = Answer(question=question, content=request.POST.get('content'), create_date=timezone.now())
answer.save()
return redirect('앱이름:detail', question_id=question.id)
|
from django.shortcuts import render, get_object_or_404, redirect
from .models import * #모델을 불러온다.
from .forms import AnswerForm #answer폼을 불러온다.
def answer_create(request, question_id):
question = get_object_or_404(Question, pk=question_id)
if request.method == "POST":
form = AnswerForm(request.POST)#post를 통해 받은 폼.
if form.is_valid():
answer = form.save(commit=False)
answer.question = question #question객체 연결.
answer.create_date = timezone.now()
answer.save()
return redirect('앱이름:detail', question_id=question.id)
else:
form = AnswerForm()
context = {'question': question, 'form': form}
return render(request, 'detail.html', context)
#폼이 적절하지 않다면 에러메시지와 함께 detail로 보낸다.
|
부록
댓글 갯수 나타내기
게시판 같은 곳을 보면 글 옆에 몇 개의 댓글이 달렸나 보여준다.
글의 리스트와 같은 곳에서 댓글 갯수를 나타내고 싶은 곳에 {{question.answer_set.count}} 형태로 달아두면 question의 하위 댓글들 숫자를 볼 수 있다.