앜 불금!!!!! 🐱🏍🐱👤
오늘은 어제 추가했던 게시판 글 상세보기 페이지 하단에 넣었던 버튼들의 기능을 실현시킨다.
오후 3시 반 정도에 게시판 구현을 마무리 짓고, 편성된 조별로 소회의실에서 나머지 시간을 보냈다.
팀원들과 아이스브레이킹, 웹 프로젝트 주제 선정, 스토리 보드 작성함~
월요일에는 인터페이스 개발 수업에 대한 첫 평가(필답)가 있을 예정!
주말 동안 여태 배우며 정리했던 내용들을 다시 점검하고, 게시판 기능을 마저 구현해야 한다.
1. 리스트로 돌아가기 버튼
JavaScript event 방식(Delegation Model)으로 처리
↓detail.html↓
<button class="btn btn-secondary" onclick="to_list()">리스트로 돌아가기</button>
↓menu_btn.js↓
function to_list() {
document.location.href = '/bbs/list/'
}
2. 삭제 버튼
템플릿 태그로 감싼 initial.id를 span 엘리먼트 안에 넣고 id를 부여함. 삭제 버튼에 event handler 넣기
↓detail.html↓
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block html_header %}
<script src="/static/js/menu_btn.js"></script>
{% endblock %}
{% block html_body %}
<div class="container">
<h1>상세보기</h1>
글 번호 : <span id="post_id">{{ detail_form.initial.id }}</span>
글 제목 : {{ detail_form.initial.b_title }}
<br>
{% bootstrap_form detail_form %}
<br>
<button class="btn btn-secondary" onclick="to_list()">리스트로 돌아가기</button>
<button class="btn btn-primary">수정</button>
<button class="btn btn-danger" onclick="delete_post()">삭제</button>
<button class="btn btn-warning" onclick="b_like()">좋아요</button>
</div>
{% endblock %}
정말 삭제할지 경고창으로 확인 후 쿼리 스트링으로 게시글 id을 문자열로 가져와 /bbd/delete/post_id 창으로 이동
↓menu_btn.js↓
function delete_post() {
// alert($('#post_id').text())
let result = confirm("정말 삭제할까요?")
if(result) {
let queryString = "?post_id=" + $('#post_id').text()
document.location.href = '/bbs/delete/' + queryString
}
}
↓bbs/urls.py↓
path('delete/', views.b_delete, name='b_delete'),
GET 방식으로 post_id와 이에 해당하는 Board 객체를 가져와서 삭제하고 게시판으로 redirect
↓views.py↓
def b_delete(request):
post_id = request.GET['post_id']
post = get_object_or_404(Board, pk=post_id)
post.delete()
return redirect('bbs:b_list')
3. 좋아요 버튼
↓detail.html↓
<button class="btn btn-warning" onclick="like_post()">좋아요</button>
↓menu_btn.js↓
function like_post() {
let queryString = "?post_id=" + $('#post_id').text()
document.location.href = '/bbs/like/' + queryString
}
↓bbs/urls.py↓
path('like/', views.b_like, name='b_like'),
GET 방식으로 post_id와 이에 해당하는 Board 객체를 가져와서 좋아요 수에 1을 더하고 저장.
글 상세보기 페이지에 만들어둔 Form으로 가져온 객체를 표현함
↓views.py↓
def b_like(request):
post_id = request.GET['post_id']
post = get_object_or_404(Board, pk=post_id)
post.b_like_count += 1
post.save()
board_detail_form = BoardDetailForm(instance=post)
context = {
'detail_form': board_detail_form
}
return render(request, 'bbs/detail.html', context)
4. 댓글 등록
게시글 상세보기 함수에 댓글 항목을 추가
↓views.py↓
def b_detail(request, board_id):
post = get_object_or_404(Board, pk=board_id)
board_detail_form = BoardDetailForm(instance=post) # post를 가지고 Model Form 객체를 만듦
comments = post.comment_set.all().order_by('-id') # 모든 댓글을 발행 역순으로 나열하라
context = {
'detail_form': board_detail_form,
'comments': comments
}
return render(request, 'bbs/detail.html', context)
block html_body 안에 댓글 양식 입력
↓detail.html↓
<tbody>
<tr>
<td>강감찬</td>
<td>더 깎아주세요!</td>
<td><button class="btn btn-danger">삭제</button></td>
</tr>
</tbody>

HTML로 직접 댓글을 입력하는 게 아닌 상세보기 페이지에서 입력할 수 있도록 변경
↓detail.html↓
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block html_header %}
<script src="/static/js/menu_btn.js"></script>
{% endblock %}
{% block html_body %}
<div class="container">
<h1>상세보기</h1>
글 번호 : <span id="post_id">{{ detail_form.initial.id }}</span>
글 제목 : {{ detail_form.initial.b_title }}
<br>
{% bootstrap_form detail_form %}
<br>
{# <a href="{% url 'bbs:b_list' %}" class="btn btn-secondary">리스트로 돌아가기</a>#}
<button class="btn btn-success" onclick="to_list()">리스트로 돌아가기</button>
<button class="btn btn-primary">수정</button>
<button class="btn btn-danger" onclick="delete_post()">삭제</button>
<button class="btn btn-warning" onclick="like_post()">좋아요</button>
</div>
<br><br>
<div class="container">
<h3>댓글</h3>
<label for="c_name">이름</label>
<input type="text" class="form-control w-25" id="c_name">
<label for="c_content">내용</label>
<input type="text" class="form-control w-50" id="c_content">
<br>
<button type="button" class="btn btn-info" onclick="create_comment()">댓글 등록</button>
<table class="table table-hover">
<thead class="thread-dark">
<tr>
<th scope="col">댓글 작성자</th>
<th scope="col">댓글 내용</th>
<th scope="col">삭제</th>
</tr>
</thead>
<tbody>
{% for comment in comments %}
<tr>
<td>{{ comment.c_author }}</td>
<td>{{ comment.c_content }}</td>
<td><button class="btn btn-danger">삭제</button></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<br><br><br>
{% endblock %}
↓menu_btn.js↓
function create_comment() {
$.ajax({
async: true,
url: "/bbs/createComment/",
type: 'GET',
data: {
board_id: $('#post_id').text(),
comment_author: $('#c_name').val(),
comment_content: $('#c_content').val()
},
dataType: 'json',
timeout: 3000,
success: function (result) {
// alert('AJAX 성공')
let tr = $("<tr></tr>")
let author_td = $("<td></td>").text(result['c_author'])
let content_td = $("<td></td>").text(result['c_content'])
let btn_td = $("<td></td>")
let btn = $("<button></button>").text("삭제").addClass("btn btn-danger")
btn_td.append(btn)
tr.append(author_td)
tr.append(content_td)
tr.append(btn_td)
$('tbody').prepend(tr)
},
error: function () {
alert('뭔가 이상해요!')
}
})
}
↓bbs/urls.py↓
path('createComment/', views.create_comment, name='create_comment'),
댓글 등록 버튼을 누르면 create_comment() 함수가 Ajax로 data가 호출되기 때문에 HttpResponse 객체가 아닌 JsonResponse(상단에서 import)로 나가야 함
↓views.py↓
from django.shortcuts import render, redirect, get_object_or_404
from bbs.models import Board, Comment
from bbs.forms import BoardForm, BoardDetailForm
from django.http import JsonResponse
def b_list(request):
posts = Board.objects.all().order_by('-id')
context = {
'posts': posts
}
return render(request, 'bbs/list.html', context)
def b_create(request):
# request 방식이 GET or POST인지 구분해서 처리
# GET 방식이면 빈 입력 상자를 출력하고,
if request.method == 'GET':
board_form = BoardForm()
context = {
'my_form': board_form
}
return render(request, 'bbs/create.html', context)
# POST 방식이면 client가 입력된 데이터를 이용해서 DB 처리
else:
board_form = BoardForm(request.POST) # client가 입력된 데이터를 가지고 있는 ModelForm
if board_form.is_valid():
board_form.save()
# 입력 받은 값 이외에 다른 컬럼의 값을 지정해서 사용할 때(좋아요 개수 10)
# new_post = board_form.save(commit=False)
# new_post.b_like_count = 10
# new_post.save()
return redirect('bbs:b_list')
def b_detail(request, board_id):
post = get_object_or_404(Board, pk=board_id)
board_detail_form = BoardDetailForm(instance=post) # post를 가지고 Model Form 객체를 만듦
comments = post.comment_set.all().order_by('-id') # 모든 댓글을 발행 역순으로 나열하라
context = {
'detail_form': board_detail_form,
'comments': comments
}
return render(request, 'bbs/detail.html', context)
def b_delete(request):
post_id = request.GET['post_id']
post = get_object_or_404(Board, pk=post_id)
post.delete()
return redirect('bbs:b_list')
def b_like(request):
post_id = request.GET['post_id']
post = get_object_or_404(Board, pk=post_id)
post.b_like_count += 1
post.save()
board_detail_form = BoardDetailForm(instance=post)
context = {
'detail_form': board_detail_form
}
return render(request, 'bbs/detail.html', context)
def create_comment(request):
comment = Comment()
comment.c_author = request.GET['comment_author']
comment.c_content = request.GET['comment_content']
comment.board_id = request.GET['board_id']
comment.save()
# AJAX로 호출되었기 때문에 그 결과가 HttpResponse 객체가 아닌 JsonResponse로 나가야 함!
# JsonResponse(결과JSON,json_dumps_params={'ensure_ascii': True})
return JsonResponse({
'c_id': comment.id,
'c_author': comment.c_author,
'c_content': comment.c_content
},
json_dumps_params={'ensure_ascii': True})
5. 댓글 삭제
↓menu_btn.js↓
function new_post() {
document.location.href = '/bbs/create/'
}
function to_list() {
document.location.href = '/bbs/list/'
}
function delete_post() {
// alert($('#post_id').text())
let result = confirm("정말 삭제할까요?")
if(result) {
let queryString = "?post_id=" + $('#post_id').text()
document.location.href = '/bbs/delete/' + queryString
}
}
function like_post() {
let queryString = "?post_id=" + $('#post_id').text()
document.location.href = '/bbs/like/' + queryString
}
function create_comment() {
$.ajax({
async: true,
url: "/bbs/createComment/",
type: 'GET',
data: {
board_id: $('#post_id').text(),
comment_author: $('#c_name').val(),
comment_content: $('#c_content').val()
},
dataType: 'json', // 서버 프로그램이 결과로 돌려주는 값은 JSON
timeout: 3000,
success: function(result) {
let tr = $("<tr></tr>").attr('id','comment_' + result['c_id'])
let author_td = $('<td></td>').text(result['c_author'])
let content_td = $('<td></td>').text(result['c_content'])
let btn_td = $('<td></td>')
let btn = $('<button></button>').text('삭제').addClass('btn btn-danger')
btn.on('click',function() {
$.ajax({
async: true,
url: '/bbs/deleteComment/',
type: 'GET',
data: {
comment_id: result['c_id']
},
dataType: 'json',
timeout: 3000,
success: function() {
alert('댓글 삭제 성공!!')
$('#comment_' + result['c_id']).remove()
},
error: function() {
alert('댓글 삭제 실패!')
}
})
})
btn_td.append(btn)
tr.append(author_td)
tr.append(content_td)
tr.append(btn_td)
$('tbody').prepend(tr)
},
error: function() {
alert('뭔가 이상해요!')
}
})
}
↓bbs/urls.py↓
# bbs App의 URLConf(http://127.0.0.1:8000/bbs/)
from django.urls import path
from bbs import views
app_name = 'bbs'
urlpatterns = [
# http://localhost::8000/bbs/list/
path('list/', views.b_list, name='b_list'),
# http://localhost::8000/bbs/create/
path('create/', views.b_create, name='b_create'),
# http://localhost::8000/bbs/<int:board_id>/detail/
path('<int:board_id>/detail/', views.b_detail, name='b_detail'),
# http://localhost::8000/bbs/delete/#post_id
path('delete/', views.b_delete, name='b_delete'),
# http://localhost::8000/bbs/like/#post_id
path('like/', views.b_like, name='b_like'),
# http://localhost::8000/bbs/createComment/#post_id
path('createComment/', views.create_comment, name='create_comment'),
# http://localhost::8000/bbs/commentDelete/
path('deleteComment/', views.delete_comment, name='delete_comment'),
]
↓views.py↓
from django.shortcuts import render, redirect, get_object_or_404
from bbs.models import Board, Comment
from bbs.forms import BoardForm, BoardDetailForm
from django.http import JsonResponse
def b_list(request):
posts = Board.objects.all().order_by('-id')
context = {
'posts': posts
}
return render(request, 'bbs/list.html', context)
def b_create(request):
# request 방식이 GET or POST인지 구분해서 처리
# GET 방식이면 빈 입력 상자를 출력하고,
if request.method == 'GET':
board_form = BoardForm()
context = {
'my_form': board_form
}
return render(request, 'bbs/create.html', context)
# POST 방식이면 client가 입력된 데이터를 이용해서 DB 처리
else:
board_form = BoardForm(request.POST) # client가 입력된 데이터를 가지고 있는 ModelForm
if board_form.is_valid():
board_form.save()
# 입력 받은 값 이외에 다른 컬럼의 값을 지정해서 사용할 때(좋아요 개수 10)
# new_post = board_form.save(commit=False)
# new_post.b_like_count = 10
# new_post.save()
return redirect('bbs:b_list')
def b_detail(request, board_id):
post = get_object_or_404(Board, pk=board_id)
board_detail_form = BoardDetailForm(instance=post) # post를 가지고 Model Form 객체를 만듦
comments = post.comment_set.all().order_by('-id') # 모든 댓글을 발행 역순으로 나열하라
context = {
'detail_form': board_detail_form,
'comments': comments
}
return render(request, 'bbs/detail.html', context)
def b_delete(request):
post_id = request.GET['post_id']
post = get_object_or_404(Board, pk=post_id)
post.delete()
return redirect('bbs:b_list')
def b_like(request):
post_id = request.GET['post_id']
post = get_object_or_404(Board, pk=post_id)
post.b_like_count += 1
post.save()
board_detail_form = BoardDetailForm(instance=post)
context = {
'detail_form': board_detail_form
}
return render(request, 'bbs/detail.html', context)
def create_comment(request):
comment = Comment()
comment.c_author = request.GET['comment_author']
comment.c_content = request.GET['comment_content']
comment.board_id = request.GET['board_id']
comment.save()
# AJAX로 호출되었기 때문에 그 결과가 HttpResponse객체가 아닌 JsonResponse가 나가야 해요!
# JsonResponse(결과JSON,json_dumps_params={'ensure_ascii': True})
return JsonResponse({
'c_id': comment.id,
'c_author': comment.c_author,
'c_content': comment.c_content
},
json_dumps_params={'ensure_ascii': True})
def delete_comment(request):
comment = get_object_or_404(Comment, pk=request.GET['comment_id'])
comment.delete()
return JsonResponse({}, json_dumps_params={'ensure_ascii': True})
1. 1/17 월 | 2. 1/18 화 | 3. 1/19 수 | 4. 1/20 목 | 5. 1/21 금 |
취업 특강 | 파이썬 환경 설정 (파이참, 아나콘다, 주피터 노트북) |
파이썬 데이터 타입 (list, tuple) |
파이썬 데이터 타입 (range, string, dictionary, set, bool) |
파이썬 사용자 정의 함수, 객체지향, 사용자 정의 클래스 |
6. 1/24 월 | 7. 1/25 화 | 8. 1/26 수 | 9. 1/27 목 | 10. 1/28 금 |
파이썬 사용자 정의 클래스, 사용자 정의 모듈 |
DB(MySQL) DBMS, MySQL 환경 설정, DB/테이블 생성, DB 입력·활용, Index |
DB(MySQL) View, 백업과 복원, DB 모델링, 관계(PK, FK), DML(CRUD), 데이터 타입 |
DB(MySQL) DML(CRUD), WHERE 조건, 패턴 매칭, SubQuery, 정렬, 그룹핑, 집계 함수, 트랜잭션(ACID 특성) |
DB(MySQL) JOIN, UNION, NOT IN, WEB |
11. 2/3 목 | 12. 2/4 금 | 13. 2/7 월 | 14. 2/8 화 | 15. 2/9 수 |
WEB WebStorm 환경 설정, HTML, CSS, JavaScript, jQuery CDN |
WEB jQuery 문법, Selector, Method |
WEB jQuery Method, Event, AJAX |
GitHub 특강 소스코드 관리, Fork, Clone, Branch, Commit, Push, Pull-Request, Rebase |
GitHub 특강 프로젝트 관리, Fetch, Rebase, Merge, Conflict |
16. 2/10 목 | 17. 2/11 금 | 18. 2/14 월 | 19. 2/15 화 | 20. 2/16 수 |
WEB jQuery AJAX, Bootstrap, Open API |
Django WSGI, MVC, MVT, ORM, 투표 시스템 |
Django MVT, ORM |
Django MVT, ORM, Redirect |
Django 게시판 |
21. 2/17 목 | 22. 2/18 금 | 23. 2/21 월 | 24. 2/22 화 | 25. 2/23 수 |
Django 게시판, Model Form |
Django 게시판, 프로젝트 조 편성 |
Django 사용자 및 권한 관리, 테스트 |
* 개념, 구조!