2023.10.24 - [Python] - [파이썬] Django로 게시판 만들기(1)
위 포스팅에서 환경설정에 따라 생성한 템플릿파일과 메소드에 대해서 설명하는 시간을 가져보겠습니다.
먼저 게시글 및 댓글을 볼수 있고 게시글 검색 기능이 있는 board.html파일입니다.
board.html에서는 게시글을 다섯개씩 볼 수 있도록 paging 기능도 구현하였습니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body style="margin:20px;">
<!-- 게시판 제목 -->
<div style="width: 95%;text-align: center;">
<h3>게시판 글</h3>
</div>
<!-- 글쓰기 링크 -->
<a href="/board/insert">글쓰기</a>
<!-- 게시글 목록 테이블 -->
<table style="width:95%;" class="table">
<tr>
<th>번호</th>
<th>제목</th>
<th>작성자</th>
<th>작성일</th>
<th>조회수</th>
</tr>
<!-- 게시글 데이터 출력 -->
{% if datas %}
{% for d in datas %}
<tr>
<td>{{d.id}}</td>
<td>
<!-- 답글의 들여쓰기를 위한 공백 추가 -->
{% with ''|center:d.nested as range %}
{% for _ in range %}
{% endfor %}
{% endwith %}
<a href="/board/content?id={{d.id}}&page={{datas.number}}">{{d.title}}</a>
</td>
<td>{{d.name}}</td>
<td>{{d.bdate.year}}.{{d.bdate.month}}.{{d.bdate.day}}</td>
<td>{{d.readcnt}}</td>
</tr>
{% endfor %}
<!-- 페이징 정보 출력 -->
<tr>
<td colspan="5" style="text-align:center;">
{% if datas.paginator.num_pages > 1 %}
<div>
{% if datas.has_previous %}
<a href="/board/list?page={{datas.previous_page_number}}">«이전</a>
{% endif %}
{% if datas.has_next %}
<a href="/board/list?page={{datas.next_page_number}}">다음»</a>
{% endif %}
(페이지:{{datas.number}}/{{datas.paginator.num_pages}})
</div>
{% endif %}
</td>
</tr>
{% else %}
<!-- 게시글이 없는 경우 -->
<tr>
<td colspan="5">글이 없습니다.</td>
</tr>
{% endif %}
<!-- 검색 폼 -->
<tr>
<td colspan="6" style="text-align: center;">
<form action="/board/search" method="post" >{%csrf_token%}
<select name="s_type">
<option value="title" selected>글제목</option>
<option value="name">작성자</option>
</select>
<input type="text" name="s_value">
<input type="submit" value="검색">
</form>
</td>
</tr>
</table>
</body>
</html>
위 파일에서 글쓰기를 클릭할 시,
<a href="/board/insert">글쓰기</a>
urls.py파일에 만들어놓은 url 경로를 통해,
path("insert",view1.insertFunc),
view1.py 파일에 존재하는 insertFunc 메소드를 실행시킵니다.
def insertFunc(request):
if request.method == 'GET':
return render(request, 'insert.html')
# GET 요청일 경우 'insert.html' 템플릿을 렌더링하여 응답
elif request.method == 'POST':
try:
gbun = 1 # group number
datas = BoardTab.objects.all()
if datas.count() != 0:
gbun = BoardTab.objects.latest('id').id + 1
# 데이터베이스에 저장된 게시글이 있으면 마지막 게시글의 id에 1을 더한 값을 gbun에 할당
BoardTab(
name=request.POST.get('name'),
passwd=request.POST.get('passwd'),
mail=request.POST.get('mail'),
title=request.POST.get('title'),
cont=request.POST.get('content'),
bip=request.META['REMOTE_ADDR'],
bdate=datetime.now(),
readcnt=0,
gnum=gbun,
onum=0,
nested=0,
).save()
# 새로운 게시글을 생성하고 저장
except Exception as e:
print('추가 에러 : ', e)
return render(request, 'error.html')
return redirect('/board/list')
# POST 요청이면, '/board/list' URL로 리다이렉트
그리고, insertFunc를 통해서 insert.html로 이동하여 게시글을 입력하는 폼을 작성하게 됩니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script>
// 페이지 로드 후 실행할 함수
window.onload = function () {
// 등록 버튼에 클릭 이벤트 리스너 추가
document.querySelector("#btnOk").onclick = chkFunc;
};
// 등록 버튼 클릭 시 실행되는 함수
function chkFunc() {
if (frm.name.value === "") {
frm.name.placeholder = "작성자를 입력하시오"; // 입력 필드에 안내 메시지 표시
frm.name.focus(); // 입력 필드에 포커스
return false; // 폼 제출 중단
}
// 나머지는 생략
frm.submit(); // 폼 제출
}
</script>
</head>
<body style="margin: 20px;">
새글 입력.
<form action="/board/insert" name="frm" method="post">
{% csrf_token %}
<table style="width: 95%;" class='table'>
<tr>
<td>작성자</td>
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>비밀번호</td>
<td><input type="text" name="passwd"></td>
</tr>
<tr>
<td>이메일</td>
<td><input type="text" name="mail"></td>
</tr>
<tr>
<td>글제목</td>
<td><input type="text" name="title"></td>
</tr>
<tr>
<td>글내용</td>
<td>
<textarea rows="5" style="width: 99%" name="content"></textarea>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center">
<!-- 등록 버튼 -->
<input type="button" value="등록" id="btnOk" class="btn btn-primary">
</td>
</tr>
</table>
</form>
</body>
</html>
이렇게 insert.html에서 작성한 글을 등록 버튼을 누를 시 해당내용이 post방식으로 서버에 보내져, 클라이언트는 board.html에서 작성했던 글을 확인할 수 있습니다.
작성한 글을 글제목 또는 작성자 이름에 따라 검색하는 기능은 board.html에서
<form action="/board/search" method="post" >{%csrf_token%}
<select name="s_type">
<option value="title" selected>글제목</option>
<option value="name">작성자</option>
</select>
<input type="text" name="s_value">
<input type="submit" value="검색">
</form>
를 통해 실행이 되며 POST방식을 통하여 글 제목 또는 작성자 정보를 서버에 넘기게 됩니다.
path("search",view1.searchFunc),
그리고, url을 통해 view1파일의 searchFunc를 실행합니다.
def searchFunc(request):
if request.method == 'POST':
# POST 요청에서 검색 타입과 검색어 값을 가져옵니다.
s_type = request.POST.get('s_type')
s_value = request.POST.get('s_value')
if s_type == 'title':
# 게시글 제목을 기준으로 검색합니다.
datas_search = BoardTab.objects.filter(title__contains = s_value).order_by('-id')
elif s_type == 'name':
# 작성자 이름을 기준으로 검색합니다.
datas_search = BoardTab.objects.filter(name__contains = s_value).order_by('-id')
# 검색 결과를 페이징 처리합니다.
paginator = Paginator(datas_search, 5) # 페이지 당 5개씩 출력
try:
page = request.GET.get('page')
except:
page = 1
try:
datas = paginator.page(page)
except PageNotAnInteger:
datas = paginator.page(1)
except EmptyPage:
datas = paginator.page(paginator.num_pages())
# 검색 결과를 board.html 템플릿에 전달합니다.
return render(request, 'board.html', {'datas':datas})
이 메소드를 통하여 작성자 또는 글 제목에 따라서 게시글을 찾을 수 있게 됩니다.
또한, board.html에서 글의 제목을 누를시 GET방식으로 서버의 view 파일의 메소드에 댓글의 아이디가 넘겨지게 되어, 작성한 글의 상세정보를 볼 수 있습니다.
<a href="/board/content?id={{d.id}}&page={{datas.number}}">{{d.title}}</a>
path("content",view1.contentFunc),
이후, urls의 경로를 타고 contentFunc을 실행시키며,
def contentFunc(request):
page = request.GET.get('page')
data = BoardTab.objects.get(id=request.GET.get('id'))
# GET 요청으로 받은 id를 가지는 데이터를 가져옴
data.readcnt = data.readcnt + 1 #조회수 +1
data.save() # 조회수 갱신
return render(request, 'content.html', {'data': data, 'page': page})
# 'content.html' 템플릿을 렌더링하고 data와 page를 전달
조회수를 갱신한 후,
content.html파일로 이동합니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
</head>
<body style="margin:20px;">
<!-- 게시글 제목 -->
<h2>* {{data.id}}번 게시글 내용 *</h2>
<!-- 게시글 동작 링크들 -->
<table class="table">
<tr style="width: 95%;">
<td style="text-align:right; width:95%">
<a href="/board/reply?id={{data.id}}">답글</a>
<a href="/board/update?id={{data.id}}">수정</a>
<a href="/board/delete?id={{data.id}}">삭제</a>
<a href="/board/list?page={{page}}">목록</a>
</td>
</tr>
</table>
<!-- 게시글 정보 테이블 -->
<table class="table">
<tr style="width: 95%; background-color: lightgray;">
<td>
작성자 : <a href="mailto:{{data.mail}}">{{data.name}} (ip:{{data.bip}})</a>
</td>
<td>작성일 : {{data.bdate}}</td>
<td>조회수 : {{data.readcnt}}</td>
</tr>
<tr>
<td colspan="3">제목 : {{data.title}}</td>
</tr>
<tr>
<td colspan="3">
<!-- 게시글 내용 -->
<textarea rows="5" style="width:100%" readonly>{{data.title}}</textarea>
</td>
</tr>
</table>
</body>
</html>
게시글 수정 및 삭제 또한 위의 방식들과 비슷합니다.
url에 글의 id를 GET방식으로 받아서 updateFunc과 deleteFunc를 실행하게 됩니다.
path("update",view1.updateFunc),
path("delete",view1.deleteFunc),
def updateFunc(request):
if request.method == 'GET':
try:
# GET 요청으로 들어온 id에 해당하는 게시글을 가져와서 update.html 템플릿에 전달합니다.
data = BoardTab.objects.get(id=request.GET.get('id'))
return render(request, 'update.html', {'data':data})
except Exception as e:
# 오류 발생 시 에러 메시지를 출력하고 error.html 템플릿을 렌더링합니다.
print('수정 자료 읽기 오류 : ', e)
return render(request,'error.html')
elif request.method == 'POST':
try:
# POST 요청으로 들어온 데이터를 기반으로 게시글을 수정합니다.
updata = BoardTab.objects.get(id=request.POST.get('id'))
# 비밀번호 비교
if updata.passwd == request.POST.get('up_passwd'):
updata.name = request.POST.get('name')
updata.mail = request.POST.get('mail')
updata.title = request.POST.get('title')
updata.cont = request.POST.get('content')
updata.save()
return redirect('/board/list') # 수정 완료 후 목록 보기
else:
# 비밀번호가 일치하지 않을 경우 에러 메시지와 함께 update.html 템플릿을 렌더링합니다.
return render(request, 'update.html', {'data':updata, 'upmsg':"비밀번호 불일치"})
except Exception as e:
# 오류 발생 시 에러 메시지를 출력하고 error.html 템플릿을 렌더링합니다.
print('수정 자료 처리 오류 : ', e)
return render(request,'error.html')
def deleteFunc(request):
if request.method == 'GET':
# GET 요청으로 들어온 id에 해당하는 게시글을 가져와서 delete.html 템플릿에 전달합니다.
try:
deldata = BoardTab.objects.get(id=request.GET.get('id'))
return render(request,'delete.html',{'data':deldata})
except Exception as e:
# 오류 발생 시 에러 메시지를 출력하고 error.html 템플릿을 렌더링합니다.
print('삭제 자료 읽기 오류 : ', e)
return render('error.html')
elif request.method == 'POST':
# POST 요청으로 들어온 데이터를 기반으로 게시글을 삭제합니다.
try:
deldata = BoardTab.objects.get(id=request.POST.get('id'))
if deldata.passwd == request.POST.get('del_passwd'):
deldata.delete()
return redirect('/board/list') #삭제 후 목록보기
else:
# 비밀번호가 일치하지 않을 경우 에러 메시지와 함께 delete.html 템플릿을 렌더링합니다.
return render(request,'error.html')
except Exception as e:
# 오류 발생 시 에러 메시지를 출력하고 error.html 템플릿을 렌더링합니다.
print('삭제 자료 처리 오류 : ', e)
return render(request,'error.html')
각각의 메소드를 수행하여 이동하는 경로인 update.html과 delete.html 파일을 만들었습니다.
update.html입니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script>
window.onload = function () {
// "수정" 버튼 클릭 시 chkFunc 함수 실행
document.querySelector("#btnUpdate").onclick = chkFunc;
};
function chkFunc() {
// 작성자 입력값 확인
if(upfrm.name.value === ""){
upfrm.name.placeholder = "작성자를 입력하시오";
upfrm.name.focus();
return false;
}
// 나머지는 생략
// 폼 전송
upfrm.submit();
}
</script>
</head>
<body style="margin: 20px;">
<!-- 게시글 수정 양식 -->
<form action="/board/update" name="upfrm" method="post">{% csrf_token %}
<input type="hidden" name="id" value="{{data.id}}">
<table style="width: 95%;" class='table'>
<tr>
<td>작성자</td>
<!-- 작성자 입력 필드, 기존 작성자 정보를 출력 -->
<td><input type="text" name="name" value="{{data.name}}"></td>
</tr>
<tr>
<td>비밀번호</td>
<!-- 비밀번호 입력 필드 -->
<td><input type="text" name="up_passwd" ><span style="color:red;">{{upmsg}}</span></td>
</tr>
<tr>
<td>이메일</td>
<!-- 이메일 입력 필드, 기존 이메일 정보를 출력 -->
<td><input type="text" name="mail" value="{{data.mail}}"></td>
</tr>
<tr>
<td>글제목</td>
<!-- 글 제목 입력 필드, 기존 글 제목 정보를 출력 -->
<td><input type="text" name="title" value="{{data.title}}"></td>
</tr>
<tr>
<td>글내용</td>
<td>
<!-- 글 내용 입력 필드, 기존 글 내용 정보를 출력 -->
<textarea rows="5" style="width: 99%" name="content">{{data.cont}}</textarea>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center">
<!-- 수정 버튼과 이전 버튼 -->
<input type="button" value="수정" id="btnUpdate" class="btn btn-primary">
<input type="button" value="이전" onclick="history.back()" class="btn btn-warning">
</td>
</tr>
</table>
</form>
</body>
</html>
update.html에서 수정한 정보들은 POST방식을 통해 서버로 데이터들이 전송이 되며, updateFunc를 실행 시키고,다시 글목록으로 돌아가집니다.
delete.html입니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script>
window.onload=function(){
// "삭제" 버튼 클릭 시 delFunc 함수 실행
document.querySelector("#btnDel").onclick=delFunc;
// "취소" 버튼 클릭 시 cancelFunc 함수 실행
document.querySelector("#btnCancel").onclick=cancelFunc;
}
function delFunc(){
// 비밀번호 입력값 확인
if(document.querySelector("#del_passwd").value===""){
document.querySelector("#del_passwd").placeholder="비밀번호 입력";
}else{
// 삭제 여부 확인
let result=confirm("정말 삭제할까요?");
if(result){
// 확인 시 폼 전송
document.querySelector("form").submit();
}
}
}
function cancelFunc(){
// "취소" 버튼 클릭 시 실행되는 함수
alert("b")
}
</script>
</head>
<body style="margin:20px;">
<h3>게시글 삭제</h3>
<!-- 게시글 삭제 양식 -->
<form action="/board/delete" method="post">{% csrf_token %}
<input type="hidden" name="id" value="{{data.id}}"/>
<table style="width:95%;" class="table">
<tr><th colspan="2">삭제하려면 비밀번호를 입력하시오</th></tr>
<tr>
<td>비밀번호</td>
<!-- 비밀번호 입력 필드 -->
<td><input type="text" name="del_passwd" id="del_passwd"></td>
</tr>
<tr>
<td colspan="2">
<!-- "삭제" 버튼과 "취소" 버튼 -->
<input type="button" value="삭제" id="btnDel">
<input type="button" value="취소" id="btnCancel">
</td>
</tr>
</table>
</form>
</body>
</html>
delete.html에서 수정한 정보들도 마찬가지로, POST방식을 통해 서버로 수정한 데이터가 전송되며, deleteFunc를 실행 시키고,다시 글목록으로 돌아가집니다.
관련 모든 메소드를 포함한
view1.py입니다.
from datetime import datetime
from django.core.paginator import Paginator, PageNotAnInteger, EmptyPage
from django.shortcuts import render, redirect
from myboard.models import BoardTab # myboard 앱에서 BoardTab 모델을 import
def mainFunc(request):
imsi = "<div><h2>메인화면</h2></div>" # HTML 형식의 문자열을 변수에 저장
return render(request, 'main.html', {'maintag': imsi})
# 'main.html' 템플릿을 렌더링하고 maintag 변수로 imsi를 전달
def listFunc(request):
data_all = BoardTab.objects.all().order_by('-gnum', 'onum')
# BoardTab 모델에서 모든 데이터를 불러오고 gnum 기준 내림차순, onum 기준 오름차순으로 정렬
paginator = Paginator(data_all, 5) # 페이지 당 5개씩 출력
try:
page = request.GET.get('page')
except:
page = 1
try:
data = paginator.page(page)
except PageNotAnInteger:
data = paginator.page(1)
except EmptyPage:
data = paginator.page(paginator.num_pages)
return render(request, 'board.html', {'datas': data})
# 'board.html' 템플릿을 렌더링하고 datas 변수로 data를 전달
def insertFunc(request):
if request.method == 'GET':
return render(request, 'insert.html')
# GET 요청일 경우 'insert.html' 템플릿을 렌더링하여 응답
elif request.method == 'POST':
try:
gbun = 1 # group number
datas = BoardTab.objects.all()
if datas.count() != 0:
gbun = BoardTab.objects.latest('id').id + 1
# 데이터베이스에 저장된 게시글이 있으면 마지막 게시글의 id에 1을 더한 값을 gbun에 할당
BoardTab(
name=request.POST.get('name'),
passwd=request.POST.get('passwd'),
mail=request.POST.get('mail'),
title=request.POST.get('title'),
cont=request.POST.get('content'),
bip=request.META['REMOTE_ADDR'],
bdate=datetime.now(),
readcnt=0,
gnum=gbun,
onum=0,
nested=0,
).save()
# 새로운 게시글을 생성하고 저장
except Exception as e:
print('추가 에러 : ', e)
return render(request, 'error.html')
return redirect('/board/list')
# POST 요청이면, '/board/list' URL로 리다이렉트
def searchFunc(request):
if request.method == 'POST':
s_type = request.POST.get('s_type')
s_value = request.POST.get('s_value')
# POST 요청에서 s_type과 s_value를 받아옴
if s_type == 'title':
# s_type이 'title'인 경우
datas_search = BoardTab.objects.filter(title__contains=s_value).order_by('-id')
# title 필드에서 s_value를 포함하는 데이터를 찾아내고 id 기준 내림차순으로 정렬
elif s_type == 'name':
datas_search = BoardTab.objects.filter(name__contains=s_value).order_by('-id')
# name 필드에서 s_value를 포함하는 데이터를 찾아내고 id 기준 내림차순으로 정렬
paginator = Paginator(datas_search, 5) # 페이지 당 5개씩 출력
try:
page = request.GET.get('page')
except:
page = 1
try:
datas = paginator.page(page)
except PageNotAnInteger:
datas = paginator.page(1)
except EmptyPage:
datas = paginator.page(paginator.num_pages)
return render(request, 'board.html', {'datas': datas})
# 'board.html' 템플릿을 렌더링하고 datas 변수로 검색 결과를 전달
def contentFunc(request):
page = request.GET.get('page')
data = BoardTab.objects.get(id=request.GET.get('id'))
# GET 요청으로 받은 id를 가지는 데이터를 가져옴
data.readcnt = data.readcnt + 1 #조회수 +1
data.save() # 조회수 갱신
return render(request, 'content.html', {'data': data, 'page': page})
# 'content.html' 템플릿을 렌더링하고 data와 page를 전달
def updateFunc(request):
if request.method == 'GET':
try:
data = BoardTab.objects.get(id=request.GET.get('id'))
return render(request, 'update.html', {'data': data})
# GET 요청으로 받은 id를 가지는 데이터를 가져와서 'update.html' 템플릿을 렌더링
except Exception as e:
print('수정 자료 읽기 오류 : ', e)
return render(request, 'error.html')
# 오류가 발생하면 'error.html' 템플릿을 렌더링
elif request.method == 'POST':
try:
updata = BoardTab.objects.get(id=request.POST.get('id'))
# POST 요청으로 받은 id를 가지는 데이터를 가져옴
if updata.passwd == request.POST.get('up_passwd'):
# 비밀번호 확인
updata.name = request.POST.get('name')
updata.mail = request.POST.get('mail')
updata.title = request.POST.get('title')
updata.cont = request.POST.get('content')
updata.save()
return redirect('/board/list') # 수정 완료 후 목록 보기
else:
return render(request, 'update.html', {'data': updata, 'upmsg': "비밀번호 불일치"})
# 비밀번호가 일치하지 않으면 'update.html' 템플릿을 렌더링하고 메시지 전달
except Exception as e
이제 게시글에 답글을 다는 메소드들을 만들어보겠습니다. 이들은 따로 view2.py 파일에 만들었습니다.
content.html파일에서
<a href="/board/reply?id={{data.id}}">답글</a>
'답글'을 클릭시 , id를 GET방식으로 받아
path("reply",view2.replyFunc),
서버에서는 replyFunc를 실행합니다.
def replyFunc(request):
try:
# request.GET을 통해 id를 받아와서 해당 게시글의 정보를 가져옴
data = BoardTab.objects.get(id=request.GET.get('id'))
context = {'data_one': data}
return render(request, 'rep/reply.html', context) # rep안에 있는 reply를 찾아감
except Exception as e:
print('댓글 대상 원글 자료 읽기 오류 : ', e)
return render(request, 'error.html')
그리고 replyFunc를 통해 reply.html로 이동합니다.
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
<script>
window.onload = function () {
// "댓글 등록" 버튼 클릭 시 chkFunc 함수 실행
document.querySelector("#btnReplyOk").onclick = chkFunc;
};
function chkFunc() {
// 작성자 필드의 값이 비어있는지 확인
if (repfrm.name.value === "") {
repfrm.name.placeholder = "작성자를 입력하시오";
repfrm.name.focus();
return false;
}
// 나머지는 생략하고 폼 제출
repfrm.submit();
}
</script>
</head>
<body style="margin:20px;">
<h3>댓글 달기</h3>
<!-- 댓글 등록 양식 -->
<form action="/board/replyok" name="repfrm" method="post">{% csrf_token %}
<!-- id, gnum, onum, nested 등의 정보를 숨겨진 필드로 전달 -->
<input type="hidden" name="id" value="{{data_one.id}}">
<input type="hidden" name="gnum" value="{{data_one.gnum}}">
<input type="hidden" name="onum" value="{{data_one.onum}}">
<input type="hidden" name="nested" value="{{data_one.nested}}">
<table style="width: 95%;" class='table'>
<tr>
<td>작성자</td>
<!-- 작성자 입력 필드 -->
<td><input type="text" name="name"></td>
</tr>
<tr>
<td>비밀번호</td>
<!-- 비밀번호 입력 필드 -->
<td><input type="text" name="passwd"></td>
</tr>
<tr>
<td>이메일</td>
<!-- 이메일 입력 필드 -->
<td><input type="text" name="mail"></td>
</tr>
<tr>
<td>글제목</td>
<!-- 글 제목 입력 필드 -->
<td><input type="text" name="title" style="width:99%;" value="[RE]{{data_one.title}}"></td>
</tr>
<tr>
<td>글내용</td>
<!-- 글 내용 입력 필드 -->
<td>
<textarea rows="5" style="width: 99%" name="content"></textarea>
</td>
</tr>
<tr>
<td colspan="2" style="text-align: center;">
<!-- "댓글 등록" 버튼과 "이전화면" 버튼 -->
<input type="button" value="댓글 등록" id="btnReplyOk" class="btn btn-primary">
<input type="button" value="이전화면" onclick="history.back()" class="btn btn-primary">
</td>
</tr>
</table>
</form>
</body>
</html>
reply.html 파일입니다.
이제 댓글을 작성하고 제출하면, 이 정보들은 POST 방식으로 서버에 전송됩니다. 서버에서는 이 POST 요청을 받아서 그 안에 포함된 데이터(글 제목, 작성자 정보 등)을 추출하고, 이 정보를 활용하여 데이터베이스에 저장합니다.
이를 통해
path("replyok",view2.replyokFunc),
replyokFunc를 실행하고,
def replyokFunc(request):
if request.method == 'POST':
try:
repGnum = int(request.POST.get('gnum'))
repOnum = int(request.POST.get('onum')) # 같은 글에서는 onum을 asc로 끌자
imsiRec = BoardTab.objects.get(id=request.POST.get('id'))
oldGnum = imsiRec.gnum
oldOnum = imsiRec.onum
if oldGnum == repGnum and oldOnum >= repOnum:
oldOnum = oldOnum + 1 # onum 갱신을 준비
# 답글 저장
BoardTab(
name=request.POST.get('name'),
passwd=request.POST.get('passwd'),
mail=request.POST.get('mail'),
title=request.POST.get('title'),
cont=request.POST.get('content'),
bip=request.META['REMOTE_ADDR'],
bdate=datetime.now(),
readcnt=0,
gnum=repGnum,
onum=oldOnum,
nested=int(request.POST.get('nested')) + 1,
).save()
return redirect('/board/list') # 댓글 작성 후 목록보기
except Exception as e:
print('답글 저장 오류: ', e)
return render(request, 'error.html')
board.html 페이지로 이동하게 됩니다.