안녕하세요
이전 포스팅 회원가입 구현하기(1)(2)에서 회원가입, 로그인, 로그아웃 기능을 구현했고,
게시판 구현하기(1)(2)에서 게시판을 구현했는데 이번 시간에는 게시판에 회원가입 기능을 추가하는 실습을 진행하겠습니다.
0. 사전 준비하기 (템플릿 확장, Bootstrap4)
[Django] Django에서 템플릿 확장의 개념과 템플릿 확장 적용하는 방법 실습하기 (tistory.com)
[Django] Bootstrap4에 대해 알아보고 Django에 Bootstrap4 부트스트랩 적용하기 (tistory.com)
실습을 진행하기 앞서 개발 환경을 맞추고자 Django 템플릿 확장과 Bootstrap4를 적용해야 합니다.
1. 이전 포스팅 참고사항 (게시판, 회원가입 구현하기)
[Django] Django 게시판 구현하기(1) Create (tistory.com)
[Django] Django 게시판 구현하기(2) Update, Delete (tistory.com)
[Django] Django 회원가입 구현하기(1) Sign Up, UserCreationForm (tistory.com)
[Django] Django 회원가입 구현하기(2) Login, Logout (tistory.com)
게시판에 회원가입 기능을 추가하려고 했는데 처음 방문하시는 분들께서는 이전 포스팅을 참고해주세요.
2. 현재 디렉터리 구조
현재 `blog`라는 프로젝트를 만들고 `blogapp`, `accounts` 앱을 프로젝트에 등록해둔 상태입니다.
3. Model 수정하기(blogapp/models.py)
# blogapp/models.py
from django.contrib.auth.models import User
from django.db import models
class Board(models.Model):
title = models.CharField(max_length=20, null=True)
content = models.TextField()
user = models.ForeignKey(User, on_delete=models.DO_NOTHING, null=True)
다음은 게시판(Board) 모델을 정의하는 코드입니다.
1. User 모델은 Django에서 제공하는 기본 모델 중 하나로, 사용자 정보를 저장하는 모델입니다. django.contrib.auth.models 모듈에서 가져옵니다.
2. Board 모델은 models.Model을 상속받아 정의됩니다. models.Model은 Django에서 제공하는 모델의 기본 클래스이며, 데이터베이스 모델을 정의할 때 사용됩니다.
3. Board 모델은 다음과 같은 필드를 가지고 있습니다.
(1) title: 최대 길이가 20인 문자열(CharField) 필드로, 게시글의 제목을 저장합니다.
(2) content: 텍스트(Text) 필드로, 게시글의 내용을 저장합니다.
(3) user: User 모델과의 관계를 나타내는 ForeignKey 필드로, 게시글을 작성한 사용자를 저장합니다.
4. on_delete=models.DO_NOTHING은 참조하는 객체(여기서는 User 객체)가 삭제되었을 때 아무 동작도 하지 않겠다는 의미입니다. null=True는 이 필드가 비어 있을 수 있다는 것을 의미합니다.
5. Board 모델은 Django의 ORM(Object-Relational Mapping)을 사용하여 데이터베이스와 상호작용할 수 있습니다. 모델을 정의한 이후에는 Django의 migration 기능을 사용하여 데이터베이스 스키마를 업데이트할 수 있습니다.
4. Migration 해서 데이터베이스에 반영하기
# 마이그레이션 파일 생성
python manage.py makemigrations board
# 마이그레이션 적용하기
python manage.py migrate
모델이 정상적으로 마이그레이션 된 것을 확인하셨다면 다음으로 폼을 수정해 주셔야 합니다.
5. Form 수정하기 (blogapp/forms.py)
from django.forms import ModelForm
from .models import *
class BoardForm(ModelForm):
class Meta:
model = Board
fields = ['title', 'content']
폼(Form)을 정의하는 코드입니다.
1. ModelForm은 Django에서 제공하는 폼 클래스 중 하나로, 모델 클래스를 기반으로 폼을 생성할 때 사용됩니다. django.forms 모듈에서 가져옵니다.
2. BoardForm 클래스는 ModelForm을 상속받아 정의됩니다.
3. BoardForm 클래스는 Board 모델과 연결되는 폼입니다. Meta 클래스를 사용하여 폼의 속성을 정의합니다.
4. Meta 클래스는 모델 폼의 메타데이터를 담고 있는 클래스입니다. model 속성은 이 폼이 사용할 모델을 지정합니다. fields 속성은 이 폼에서 사용할 필드를 지정합니다. 위 코드에서는 Board 모델에서 title과 content 필드를 사용하도록 지정되어 있습니다.
5. BoardForm 클래스를 사용하면, Board 모델의 필드와 동일한 이름을 가진 HTML form 요소를 쉽게 생성할 수 있습니다. 이 폼으로부터 제출된 데이터는 Board 모델 객체로 변환하여 데이터베이스에 저장할 수 있습니다.
6. blogapp View 수정하기 (blogapp/views.py)
# blogapp/views.py
from django.shortcuts import render, redirect
from .forms import *
from .models import *
def board(request):
if request.method == 'POST':
title = request.POST['title']
content = request.POST['content']
user = request.user
board = Board(
title=title,
content=content,
user=user,
)
board.save()
return redirect('board')
else:
boardForm = BoardForm
board = Board.objects.all()
context = {
'boardForm': boardForm,
'board': board,
}
return render(request, 'board.html', context)
def boardEdit(request, pk):
board = Board.objects.get(id=pk)
if request.method == "POST":
board.title = request.POST['title']
board.content = request.POST['content']
board.user = request.user
board.save()
return redirect('board')
else:
boardForm = BoardForm
return render(request, 'update.html', {'boardForm':boardForm})
def boardDelete(request, pk):
board = Board.objects.get(id=pk)
board.delete()
return redirect('board')
board라는 게시판(Board) 기능을 구현하는 뷰(View) 함수를 정의하는 코드입니다.
1. board 함수는 HTTP 요청 방식에 따라 다른 동작을 수행합니다. 만약 POST 요청이면 새로운 글을 게시판에 등록합니다. GET 요청이면 게시판을 보여줍니다.
2. request.user는 현재 로그인한 사용자를 나타내며, Board 모델에서 user 필드와 연결되어 있습니다.
3. 새로운 글을 게시하기 위해 Board 모델 객체를 생성하고, 데이터베이스에 저장합니다. 이후에는 게시판 화면으로 리다이렉트합니다.
4. boardEdit 함수는 게시판의 글을 수정하는 뷰입니다. 수정 대상 글의 id 값을 파라미터로 받습니다.
5. Board 모델에서 get() 메서드를 사용하여 수정 대상 글의 객체를 가져옵니다.
6. POST 요청이면, 수정된 글의 정보를 Board 모델 객체에 저장하고 데이터베이스에 업데이트합니다. 이후에는 게시판 화면으로 리다이렉트합니다.
7. GET 요청이면, 수정 대상 글을 편집할 수 있는 폼을 보여줍니다.
8. boardDelete 함수는 게시판의 글을 삭제하는 뷰입니다. 삭제 대상 글의 id 값을 파라미터로 받습니다.
9. Board 모델에서 get() 메서드를 사용하여 삭제 대상 글의 객체를 가져옵니다.
10. delete() 메서드를 사용하여 데이터베이스에서 객체를 삭제하고, 이후에는 게시판 화면으로 리다이렉트합니다.
지난 시간에 작성했던 View와 대부분 유사합니다. 다만 달라진 곳은 writer를 user로 받아주는 것이죠.
그런 후 저장하면 요청한 사용자의 아이디가 board.user에 저장됩니다.
7. 템플릿 수정하기 (blogapp/templates/board.html)
<!-- blogapp/templates/board.html -->
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block content %}
<div style="width:1200px; margin:0px auto;">
<h2 style="text-align:center;">회원가입 게시판</h2><br>
{% if board %}
<table style="text-align:center; width:1200px; border:1px solid black;" class="table">
<thead>
<tr class="th_color">
<th>번호</th>
<th>제목</th>
<th>내용</th>
<th>작성자</th>
<th>수정하기</th>
<th>삭제하기</th>
</tr>
</thead>
{% for board_list in board %}
<tbody>
<tr class="td_color" >
<td>{{ board_list.pk }}</td>
<td>{{ board_list.title }}</td>
<td>{{ board_list.content }}</td>
<td>{{ board_list.user }}</td>
<td><button class="btn btn-secondary btn-sm rounded-pill" onclick="location.href='/edit/{{board_list.pk}}'">수정</button></td>
<td><button class="btn btn-danger btn-sm rounded-pill" onclick="location.href='/delete/{{board_list.pk}}'">삭제</button></td>
</tr>
</tbody>
{% endfor %}
</table>
{% endif %}
<div style="width:500px; margin:0px auto;">
<form action="" method="POST" style="max-width:500px;">
{% csrf_token %}
{% bootstrap_form boardForm %}
<button type="submit" class="btn btn-primary rounded-pill col-12">POST</button>
</form>
</div>
</div>
{% endblock %}
이전에는 [board_list.writer]를 써서 writer를 입력받아 출력했는데 여기서는 요청한 유저의 아이디를 출력해 주게 됩니다.
8. 템플릿 확장 파일 수정하기
1. 템플릿 확장 파일 디렉터리 구조
파일 구조를 보고 정확한 위치에 생성해 주세요
<!-- templates/base.html -->
{% load static %}
<html lang="ko">
<head>
{% include 'head.html' %}
</head>
<body>
{% include 'header.html' %}
<br><hr>
{% block content %}
{% endblock %}
</body>
</html>
템플릿 확장에서 [base.html] 파일입니다. head, header.html로 head와 header도 따로 모듈화하였습니다.
2. header.html 파일 생성하기
<!-- templates/header.html -->
<div>
<ul>
{% if user.is_authenticated %}
<div class="logout_div">
<ul class="underline-hover">
<li class="logout_text"><a href="{% url 'board' %}"><span>홈</span></a></li>
<li class="logout_text"><a href="{% url 'board' %}"><span>게시판</span></a></li>
<li class="logout_text"><a href="{% url 'logout' %}"><span>로그아웃</span></a></li>
</ul>
</div>
{% else %}
<div class="login_div">
<ul class="underline-hover">
<li class="login_text"><a href="{% url 'login' %}"><span>로그인</span></a></li>
<li class="login_text"><a href="{% url 'signup' %}"><span>회원가입</span></a></li>
</ul>
</div>
{% endif %}
</ul>
</div>
다음은 Navigation 버튼과 header 구성을 하기 위한 header 템플릿입니다.
9. Style Sheet 추가하기 (CSS 추가)
1. 정적 파일 폴더 구조
.wrapper {
border: 1px solid black;
width: 400px;
padding: 30px;
box-sizing: border-box;
margin: auto;
weight: bold;
}
input[type=text] {
width: 100%;
padding: 8px;
margin: 10px 0;
border-radius: 5px;
border: 1px solid lightgray;
box-sizing: border-box;
}
input[type=email] {
width: 100%;
padding: 8px;
margin: 10px 0;
border-radius: 5px;
border: 1px solid lightgray;
box-sizing: border-box;
}
input[type=password] {
width: 100%;
padding: 8px;
margin: 10px 0;
border-radius: 5px;
border: 1px solid lightgray;
box-sizing: border-box;
}
input[type=submit] {
width: 100%;
background-color: dodgerblue;
color: #fff;
padding: 7px;
margin-top: 15px;
border-radius: 5px;
border: none;
}
.login_div,
.logout_div {
display: flex;
padding: 10px 10px;;
float: right;
margin-top: -10px;
}
.underline-hover {
background-color: #fff;
margin: 0;
}
.underline-hover li{
list-style: none;
display: inline-block;
margin: 0 30px;
}
.underline-hover li a {
color: black;
text-decoration: none;
position: relative;
}
.underline-hover li a:before {
content: '';
background-color: dodgerblue;
width: 0;
height: 2px;
position: absolute;
left: 50%; /*right로 바꾸면 오른쪽에서*/
transform: translateX(-50%);
bottom: -10px;
transition: 0.3s;
}
.underline-hover li a:hover:before {
width: 100%;
}
.table {
border-collapse: collapse;
border-top: 3px solid #168;
}
.table th {
color: #168;
background: #f0f6f9;
text-align: center;
}
.table th, .table td {
border: 1px solid #ddd;
}
.table th:first-child, .table td:first-child {
border-left: 0;
}
.table th:last-child, .table td:last-child {
border-right: 0;
}
.table tr td:first-child{
text-align: center;
}
.table caption{caption-side: bottom; display: none;}
.table th:nth-child(3) {
width:700px;
}
.table .td_color td {
vertical-align:middle;
}
다음은 게시판 스타일을 위한 CSS 소스 코드입니다.
10. 서버 실행하기
python manage.py runserver
서버를 실행시킨 후에 127.0.0.1:8000에 접속하여 확인합니다.
오른쪽 상단에 로그인을 눌러서 로그인한 후에 게시글을 작성해보도록 하겠습니다.
오른쪽 상단에 메뉴 팝업이 로그인 전에는 로그인과 회원가입이었는데 로그인한 후에는 홈, 게시판, 로그아웃으로 바뀐 것을 확인할 수 있습니다. 이것은 header.html에서 템플릿을 수정해주었기 때문입니다.
{% if user.is_authenticated %}
{% if user.is_authenticated %}는 Django 템플릿 언어의 조건문(conditional statement) 중 하나로, 현재 로그인한 사용자가 인증되었는지 여부를 판별하는 조건입니다.
user.is_authenticated는 User 모델 객체의 is_authenticated 속성으로, 로그인한 사용자가 인증되었는지 여부를 나타냅니다. 로그인한 사용자가 인증되면 True를 반환하고, 인증되지 않은 경우 False를 반환합니다.
따라서 {% if user.is_authenticated %}는 현재 로그인한 사용자가 인증되었으면 조건이 참이 되어 해당 블록 내의 코드를 실행하고, 그렇지 않으면 조건이 거짓이 되어 해당 블록을 무시하고 넘어가는 역할을 합니다.
이번 시간에는 이전 시간에 게시판을 구현한 것에 회원가입, 로그인, 로그아웃 기능을 추가하는 실습을 진행했습니다.
감사합니다.
'Framework > Django' 카테고리의 다른 글
[Django] Select option 선택한 옵션으로 이동하고 선택한 값 GET으로 받기, 월별 데이터 출력하기 (2) | 2021.03.17 |
---|---|
[Django] Django에서 Page에 대해 알아보고 페이징 처리하기 Pagination (2) | 2021.02.24 |
[Django] Django 회원가입 구현하기(2) Login, Logout (0) | 2021.02.23 |
[Django] Django 회원가입 구현하기(1) Sign Up, UserCreationForm (2) | 2021.02.23 |
[Django] Django 게시판 구현하기(2) Update, Delete (0) | 2021.02.08 |
클라우드, 개발, 자격증, 취업 정보 등 IT 정보 공간
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!