210201_01_Django_(3)_게시판 웹 어플리케이션 예제
1. Model 개발
1) 테이블 정의 : models.py
2) Admin 사이트에 테이블 반영 : admins.py
3) 데이터베이스 변경 사항 반영 : manage.py makemigrations
manage.py migrate
1) 게시판 테이블 정의
> 필요한 테이블 정의 : User 테이블과 Board 테이블 생성
models.py
from django.db import models
from django.db.models.deletion import CASCADE, SET_DEFAULT, SET_NULL
//Cascade : 부모 레코드 삭제 시 자식 레코드도 함께 삭제
//Set_Default : 부모 레코드 삭제 시 외래 키를 Default 값으로 변경
//Set_Null : 부모 레코드 삭제 시 외래 키를 Null 값으로 변경
# Create your models here.
class User(models.Model):
user_name = models.CharField(max_length=200, null=False)
user_id = models.CharField(max_length=200, null=False, primary_key=True)
user_password = models.CharField(max_length=200, null=False)
def __str__(self):
return self.user_name
class Board(models.Model):
title = models.CharField(max_length=100)
content = models.CharField(max_length=500)
writer_id = models.ForeignKey(User, on_delete=SET_DEFAULT, default="")
// on_delete=SET_DEFAULT, default="" : 유저 삭제 시 게시물의 유저 ID가 Default값인 ""로 변경
pub_date = models.DateTimeField('date published')
def __str__(self):
return self.content
2) Admin 페이지에 테이블 반영
admins.py
from django.contrib import admin
from board.models import Board, User
# Register your models here.
admin.site.register(Board)
admin.site.register(User)
3) 데이터베이스에 변경 사항 적용
> python manage.py makemigrations
python manage.py migrate
2. View와 Template 개발
1) url 등록
2) view : 작동할 함수 정의
3) template : HTML 문서 작성
1) URL 과 View 이름 매핑
myDjangoSite2/urls.py
from django.conf.urls import url
from django.contrib import admin
from django.urls import path,include
urlpatterns = [
url(r'^admin/', admin.site.urls),
path('board/', include('board.urls')),
// board/ 뒤에 오는 url 주소 > board.url에 등록
]
myDjangoSite2/board/urls.py
from django.urls import path
from board import views
app_name = 'board'
urlpatterns = [
// board/ 뒤에 오는 url 주소 정의
path('login/', views.login, name='login'),
// login.html Template : 로그인 화면
path('loginProcess/', views.loginProcess, name='loginProcess'),
// 로그인 성공 시 /boardList/redirect
path('', views.boardList, name='board'),
// boardList.html : 게시판 글 목록
path('boardList/<int:curr_page>', views.boardList, name='boardList'),
// boardList.html : 게시판 글 목록
path('boardDetail/<int:board_id>', views.boardDetail, name='boardDetail'),
// boardDetail.html : 게시판 글 상세보기
]
2) View index() 및 template 작성
a. views.py : view index() 작성
from django.shortcuts import render
# Create your views here.
def login(request):
return render(request, "boardList.html")
def loginProcess(request):
return render(request, "boardList.html")
def boardList(request, curr_page = 1):
return render(request, "boardList.html")
def boardDetail(request, board_id = 1):
return render(request, "boardList.html")
b. template/boardList.html : template 작성
폼(Form) 클래스와 세션(Session), 리다이렉트(Redirect)
폼(Form) 클래스
> html 문성 작성시 태그를 자동으로 생성해주는 클래스
> 폼 클래스를 미리 객체를 만들어 놓은 후에 view와 html 에서 사용하면 자동으로 파라미터를 가져다가 사용한다.
1) forms.py 에 클래스 정의 |
폼 클래스의 장점
1. form 생성에 필요한 데이터를 폼 클래스로 구조화
2. 폼 클래스의 데이터로 렌더링하여 HTML form 생성
3. 사용자로부터 제출된 form 과 data 수신과 처리
세션 (Session)
> 논리적인 연결
> 네트워크 망에서 사용자 간의 또는 컴퓨터 간의 통신을 위한 논리적인 연결 상태
> 논리적인 연결 상태를 유지하기 위하여 세션id 를 부여
> 세션id가 유지되는 동안 논리적인 연결 유지
세션 ID 의 예시
> 네이버에 로그인하면 WAS 에서 사용자에게 세션 ID 부여
> 브라우저를 닫기 전까지 세션 ID 유지
> 세션 ID 가 유지되는 동안 로그인한 권한 유지
> 브라우저 닫는 순간 세션 ID 삭제
> 다시 브라우저를 열면 로그인했던 세션ID 가 없기 때문에 로그아웃된 상태
- 세션에서 값을 얻을 시
data = request.session.get("세션 이름")
- 세션에서 값을 저장 시 : 로그인 성공시 세션에 사용자 이름 등록
request.session['세션 이름'] = 값
//request.session['loginuser'] = user.user_name
리다이렉트 (Redirect)
> 방향재지정
> 웹 서버에 URL 요청이 들어왔을 때, 서버에서 다른 URL로 요청을 돌려서 브라우저의 방향을 재지정해 주는 것
> 리다이렉션이 발생할 시 요청한 URL이 아닌 다른 URL 주소로 바뀐다
1. 로그인 기능
1) 로그인 폼 클래스 생성
forms.py
class LoginForm(forms.Form):
login_id = forms.CharField(label = "아이디", max_length=100, required=True)
login_pw = forms.CharField(label = "패스워드", max_length=100, required=True, widget=forms.PasswordInput)
2) 로그인 페이지 생성
templates/login.html
<form action = "{% url 'board:loginProcess' %}" method="post">
// submit 버튼을 눌렀을 때 action > url : board.loginProcess 요청
{% csrf_token %}
<table>
{{ form }}
</table>
<input type = "submit" value="Login"/>
</form>
3) login 함수 수정
views.py : login()
def login(request):
form = LoginForm()
return render(request, "login.html", {'form':form})
2. 로그인 처리 기능
1) loginProcess 함수 수정
views.py : loginProcess()
def loginProcess(request):
form = LoginForm(request.POST)
errormessage = ""
if form.is_valid():
login_id = form.cleaned_data["login_id"]
login_pw = form.cleaned_data["login_pw"]
print(login_id, login_pw)
try:
user = User.objects.get(pk=login_id, user_password=login_pw)
print(user)
if user:
request.session["loginuser"] = user.user_name
return HttpResponseRedirect("/board/boardList/1")
// 로그인 성공 시 리다이렉트 boardList/1 로 이동
else:
errormessage = "1 Login Failed. User ID and PW do not Match"
context = {"errormessage":errormessage}
return render(request, "login.html", context)
except(User.DoesNotExist):
errormessage = "2 Login Failed. User does not Exist"
context = {"errormessage":errormessage}
return render(request, "login.html", context)
return render(request, "boardList.html")
로그아웃을 하고 싶다면 Session_id 를 invalid 시키는 함수를 사용한다.
2) 에러 메세지 추가
templates/login.html
<body>
{% if errormessage %} // 에러메세지가 존재할 시
{{ errormessage }} // 에러메세지 출력
{% endif %} // 조건문 종료
<form action = "{% url 'board:loginProcess' %}" method="post">
{% csrf_token %}
<table>
{{ form }}
</table>
<input type = "submit" value="Login"/>
</form>
</body>
3. 게시판 목록보기 기능
1) boardList 함수 수정
views.py : boardList()
def boardList(request, curr_page = 1):
if not request.session.get("loginuser"):
return HttpResponseRedirect("/board/login")
cntPerPage = 10
endCnt = curr_page * cntPerPage
startCnt = endCnt - cntPerPage
print(startCnt, endCnt)
totalCnt = Board.objects.count()
tpn = int(totalCnt/cntPerPage+1)
totalPageCnt = []
for i in range(1, tpn+1):
totalPageCnt.append(i)
board_list = Board.objects.all().order_by('-id')[startCnt:endCnt]
context = {"board_list":board_list, "totalPageCnt":totalPageCnt, "curr_Page":curr_page}
return render(request, "boardList.html",context)
2) 게시판 페이지 생성
templates/boardList.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>게시판 목록</title>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h1> 게시판 글목록 </h1>
<p>{{ request.session.loginuser }} 님 안녕하세요.</p>
<p></p>
<table class="table table-hover">
<tr>
<th>글번호</th><th>제목</th><th>작성자</th><th>등록일</th>
</tr>
{% if board_list %}
{% for board in board_list %}
<tr>
<td>{{board.id}}</td>
<td><a href = "{% url 'board:boardDetail' board.id %}">{{board.title}}</a></td>
// boardDetail 요청 > 요청할 때, board.id 를 가져와서 boardDetail/board.id로 넘겨줌
<td>{{board.writer_id}}</td>
<td>{{board.pub_date}}</td>
</tr>
{% endfor %}
{% endif %}
</table>
<table>
<tr>
<td>페이지 번호 </td>
<td>
{% for p in totalPageCnt %}
{% if curr_page != p %}<a href="{% url 'board:boardList' p %}" >{{p}} </a>
{% else %} {{ p }}
{% endif %}
{% endfor %}
</td>
</tr>
</table>
</div>
</body>
</html>
4. 게시판 글 상세보기 기능
1) boardDetail 함수 수정
views.py
def boardDetail(request, board_id = 1):
if not request.session.get("loginuser"):
return HttpResponseRedirect("/board/login")
board = Board.objects.get(pk=board_id)
context = {"board":board}
return render(request, "boardDetail.html", context)
2) 게시판 상세보기 페이지 생성
templates/boardDetail.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>게시판글 상세 보기 </title>
</head>
<body>
<div class="container">
<h1>
{{ board.title }}
</h1>
<p>
{{ board.content }}
</p>
</div>
<p> 작성자 : {{ board.writer_id }}</p>
<p> <a href="{% url 'board:board' %}" > 글목록 보기 </a> </p>
</body>
</html>