Python Django 웹 프레임워크(8) - Blog project 개발
Python 기초강의는 여러 절로 구성되어 있습니다.
- Python 기초강의(1) - Introduction
- Python 기초강의(2) - Python 기본
- Python 기초강의(3) - Python 제어문
- Python 기초강의(4) - Python function
- Python 기초강의(5) - Python 연습문제(1)
- Python 기초강의(6) - Python 객체지향
- Python 기초강의(7) - Python Magic Function
- Python 기초강의(8) - Python First Class
- Python 기초강의(9) - Python Closure
- Python 기초강의(10) - Python Decorator
- Python 기초강의(11) - Python Generator
- Python 기초강의(12) - Python Module
- Python 기초강의(13) - Python Exception & File
- Python 기초강의(14) - Python 연습문제(2)
- Python Django 웹 프레임워크(1) - introduction
- Python Django 웹 프레임워크(2) - Poll project 개발(1)
- Python Django 웹 프레임워크(3) - Poll project 개발(2)
- Python Django 웹 프레임워크(4) - Poll project 개발(3)
- Python Django 웹 프레임워크(5) - Poll project 개발(4)
- Python Django 웹 프레임워크(6) - Poll project 개발(5)
- Python Django 웹 프레임워크(7) - Django의 개발방식
- Python Django 웹 프레임워크(8) - Blog project 개발
Blog project 개발
Poll Project의 내용을 기반으로 이번에는 ModelForm을 이용한 CRUD 구현 및 Django에 Bootstrap4를 적용해 보도록 하겠습니다.
project 생성
새로운 project blog를 생성합니다.
C:/python-Django> django-admin startproject blog
project와 application을 모두 포함하는 폴더 이름을 MyBlog로 변경합니다.
C:/python-Django> move blog MyBlog
working directory를 MyBlog 폴더로 변경합니다.
C:/python-Django> cd MyBlog
posts application을 생성합니다.
C:/python-Django/MyBlog> python manage.py startapp posts
이후부터는 PyCharm을 이용해 작업을 진행합니다.
project 환경설정
환경설정을 위해 project 폴더의 settings.py
파일을 수정합니다.
기본적인 DEBUG=TRUE
설정에 따른 ALLOWED_HOSTS
에 대한 내용을
다음과 같이 수정합니다.
ALLOWED_HOSTS = ['localhost', '127.0.0.1']
INSTALLED_APPS
부분에 posts
application을 등록합니다.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'posts.apps.PostsConfig'
]
blog project 폴더안에 templates
폴더를 생성한 후
TEMPLATES
부분을 수정하여 해당 templates
폴더를
기본 Template 경로로 설정합니다.
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'blog', 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
],
},
},
]
TIME_ZONE
부분은 세계표준시에서 한국시간으로 변경합니다.
TIME_ZONE = 'Asia/Seoul'
Static File(CSS, JavaScript, Image)을 사용하기 위해서 Static File 폴더를 지정하고 폴더를
BASE_DIR
하단에 생성합니다.
STATIC_URL = '/static/'
STATICFILES_DIRS = [
os.path.join(BASE_DIR, 'static')
]
기본 Table 생성
기본 테이블을 생성하기 위해 다음의 명령을 수행합니다.
C:/python-Django/MyBlog> python manage.py migrate
관리자 계정 생성
관리자 page에 접속하기 위한 계정을 생성합니다.
C:/python-Django/MyBlog> python manage.py createsuperuser
서버 기동
project가 정상적으로 생성되었는지 확인하기 위해 내장서버를 이용해 deploy합니다.
C:/python-Django/MyBlog> python manage.py runserver
Admin Page 접속 확인
http://localhost:8000/admin
으로 접속 후 관리자 계정으로 로그인
Model 생성
Model을 생성하기 위해 posts application 내의 models.py
파일에 다음과 같은 내용을
입력합니다.
class Post(models.Model):
author = models.CharField('작성자', max_length=20)
contents = models.CharField('글내용', max_length=100)
def __str__(self):
return self.contents
Admin Page에 반영하기 위해서 posts application 내의 admin.py
에 class를 등록합니다.
from django.contrib import admin
from posts.models import Post
admin.site.register(Post)
Database 변경사항을 반영하기 위해서 migration 초안을 생성하고 설정된 Schema를 Database에 실제로 적용해야 합니다.
마이그레이션 초안을 생성하기 위해서 다음과 같이 실행합니다.
C:/python-Django/MyBlog> python manage.py makemigrations
설정된 Schema를 Database에 적용하기 위해서 다음과 같이 실행합니다.
C:/python-Django/MyBlog> python manage.py migrate
URL 경로 설정
blog project의 urls.py
파일을 다음과 같이 수정하여 계층적으로 URL을 관리하기 위한 설정을
합니다.
# blog/urls.py
from django.contrib import admin
from django.urls import path, include
from django.conf.urls import url
from django.views.generic.base import TemplateView
urlpatterns = [
url(r'^$', TemplateView.as_view(template_name='index.html'),
name='home'),
path('admin/', admin.site.urls),
path('posts/', include('posts.urls'))
]
/posts/
경로로 들어오는 모든 request를 처리하기 위해서
posts application의 urls.py
파일을 다음과 같이 작성합니다.
# posts/urls.py
from django.urls import path
from . import views
app_name = 'posts'
urlpatterns = [
path('list/', views.p_list, name='list'),
]
약간의 코드를 추가해 http://localhost:8000
에 대한 Homepage설정을 추가했습니다. blog project
폴더안에 templates
폴더 안에 index.html
을 위치시킵니다. Bootstrap Example 중 하나를 이용해서
처리했습니다.
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Blog Project</title>
<!-- Bootstrap core CSS -->
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css"
integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk"
crossorigin="anonymous">
<!-- Custom styles for this template -->
<link href="/static/css/cover.css" rel="stylesheet">
</head>
<body class="text-center">
<div class="cover-container d-flex w-100 h-100 p-3 mx-auto flex-column">
<header class="masthead mb-auto">
<div class="inner">
<h3 class="masthead-brand">My Blog</h3>
</div>
</header>
<main role="main" class="inner cover">
<h1 class="cover-heading">Blog Project</h1>
<p class="lead">Django Framework</p>
<p class="lead">
<a href="/posts/list/" class="btn btn-lg btn-secondary">Enter BBS</a>
</p>
</main>
<footer class="mastfoot mt-auto">
<div class="inner">
<p>Copyright 2020</p>
</div>
</footer>
</div>
</body>
</html>
기본 Template 설정
하나의 html 파일을 생성해 모든 template 파일의 base html
로 사용합니다.
blog project folder 하단의 templates
폴더안에 기본적인 형태로 base.html
을 생성합니다.
Django에 Bootstrap4을 적용하기 위해서는 django-bootstrap4를 설치해야 합니다. 아래의 명령어로 package를 설치합니다.
pip install django-bootstrap4
설치가 완료된 다음에 blog project 폴더안의 settings.py
내
INSTALLED_APPS
을 다음과 같이 수정하여 bootstrap application을 추가합니다.
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'posts.apps.PostsConfig',
'bootstrap4',
]
이후에 기본적으로 생성된 base.html
에 Bootstrap을 사용하기 위해서 CDN을 설정합니다.
해당 CDN은 Bootstrap 홈페이지에서 copy해서 사용합니다.
아래와 같이 base.html을 수정합니다.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css" integrity="sha384-9aIt2nRpC12Uk9gS9baDl411NQApFmC26EwAOH8WgZl5MYYxFfc+NcPb1dKGj7Sk" crossorigin="anonymous">
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.0/dist/umd/popper.min.js" integrity="sha384-Q6E9RHvbIyZFJoft+2mJbHaEWldlvI9IOYy5n3zV9zzTtmI3UksdQRVvoxMfooAo" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js" integrity="sha384-OgVRvuATP1z7JjHLkuOU7Xw704+h835Lr+6QL9UvYjZE3Ipu6Tp75j7Bh/kR0JKI" crossorigin="anonymous"></script>
</head>
<body>
{% block container %}
{% endblock %}
</body>
</html>
Model Form 생성
Model Form을 이용해서 model
과 fields
를 지정하면 Model Form이 자동으로 폼 필드를 생성해주기 때문에
Form 처리를 상당히 쉽게 처리할 수 있습니다.
어떤 Model을 기반으로 폼을 작성할 것인지를 Meta.model
에 지정하고
fields
는 Model class의 field 중 일부만 폼 클래스에서 사용하고자 할 때 지정하는 옵션입니다.
posts application 폴더 내에 forms.py
파일을 생성한 후 아래의 코드와 같이 Model Form class를 생성합니다.
from django import forms
from .models import Post
class PostForm(forms.ModelForm):
class Meta:
model = Post
fields = ['author', 'contents']
list 페이지 작성
posts application의 views.py
의 내용을 수정합니다.
from django.shortcuts import render
from posts.models import Post
def p_list(request):
posts = Post.objects.all().order_by('-id')
return render(request, 'list.html', {'posts': posts})
list.html
파일을 Bootstrap을 이용해서 수정합니다.
{% extends 'base.html' %}
{% block container %}
<script src="/static/js/posts.js"></script>
<div class="container">
<h1>Bulletin Board System(BBS)</h1>
<button type="button" class="btn btn-primary"
onclick="new_post()">새글 작성</button>
<div class="m-1"></div>
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">글작성자</th>
<th scope="col">글내용</th>
<th scope="col">수정</th>
<th scope="col">삭제</th>
</tr>
</thead>
<tbody>
{% for post in posts %}
<tr>
<th scope="row">{{ post.id }}</th>
<td>{{ post.author }}</td>
<td>{{ post.contents }}</td>
<td></td>
<td></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
create 페이지 작성
views.py
내용을 수정합니다.
POST
방식일때와 GET
방식일때를 구분하여 ModelForm을 create.html로 전달합니다.
POST
방식일 경우는 ModelForm객체에 데이터가 담겨서 저장되어야 하는 경우이며 GET
방식인
경우는 사용자에게 빈 양식을 보여주기 위해서 사용됩니다.
from django.shortcuts import render, redirect
from posts.models import Post
from posts.forms import PostForm
def p_list(request):
posts = Post.objects.all().order_by('-id')
return render(request, 'list.html', {'posts': posts})
def p_create(request):
# POST 방식
if request.method == 'POST':
post_form = PostForm(request.POST)
if post_form.is_valid():
post_form.save()
return redirect('posts:list')
# GET 방식
else:
post_form = PostForm()
return render(request, 'create.html', {'post_form': post_form})
create.html
파일을 Bootstrap을 이용해서 수정합니다.
{% extends 'base.html' %}
{% load bootstrap4 %}
{% block container %}
<div class="container">
<h1>New Post</h1>
<form method="post">
{% csrf_token %}
<!-- {{ post_form }}-->
{% bootstrap_form post_form %}
<button type="submit" class="btn btn-primary">등록</button>
</form>
</div>
{% endblock %}
delete 기능 작성
이번에는 list 화면에서 삭제버튼을 붙여서 delete
기능을 구현해 보겠습니다.
urls.py
를 수정합니다.
from django.urls import path
from . import views
app_name = 'posts'
urlpatterns = [
path('list/', views.p_list, name='list'),
path('create/', views.p_create, name='create'),
path('<int:post_id>/delete/', views.p_delete, name='delete'),
]
views.py
를 수정합니다.
from django.shortcuts import render, redirect
from posts.models import Post
from posts.forms import PostForm
def p_list(request):
posts = Post.objects.all().order_by('-id')
return render(request, 'list.html', {'posts': posts})
def p_create(request):
# POST 방식
if request.method == 'POST':
post_form = PostForm(request.POST)
if post_form.is_valid():
post_form.save()
return redirect('posts:list')
# GET 방식
else:
post_form = PostForm()
return render(request, 'create.html', {'post_form': post_form})
def p_delete(request, post_id):
post = Post.objects.get(id=post_id)
post.delete()
return redirect('posts:list')
list.html
을 수정해서 버튼을 붙입니다.
{% extends 'base.html' %}
{% block container %}
<script src="/static/js/posts.js"></script>
<div class="container">
<h1>Bulletin Board System(BBS)</h1>
<button type="button" class="btn btn-primary"
onclick="new_post()">새글 작성</button>
<div class="m-1"></div>
<table class="table table-hover">
<thead class="thead-dark">
<tr>
<th scope="col">#</th>
<th scope="col">글작성자</th>
<th scope="col">글내용</th>
<th scope="col">수정</th>
<th scope="col">삭제</th>
</tr>
</thead>
<tbody>
{% for post in posts %}
<tr>
<th scope="row">{{ post.id }}</th>
<td>{{ post.author }}</td>
<td>{{ post.contents }}</td>
<td></td>
<td><a href="{% url 'posts:delete' post.id %}" class="btn btn-danger">삭제</a></td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endblock %}
update 기능 작성
마지막으로 수정기능을 구현해보겠습니다.
urls.py
파일을 수정합니다.
from django.urls import path
from . import views
app_name = 'posts'
urlpatterns = [
path('list/', views.p_list, name='list'),
path('create/', views.p_create, name='create'),
path('<int:post_id>/delete/', views.p_delete, name='delete'),
path('<int:post_id>/update/', views.p_update, name='update'),
]
views.py
파일을 수정합니다.
from django.shortcuts import render, redirect, get_object_or_404
from posts.models import Post
from posts.forms import PostForm
def p_list(request):
posts = Post.objects.all().order_by('-id')
return render(request, 'list.html', {'posts': posts})
def p_create(request):
# POST 방식
if request.method == 'POST':
post_form = PostForm(request.POST)
if post_form.is_valid():
post_form.save()
return redirect('posts:list')
# GET 방식
else:
post_form = PostForm()
return render(request, 'create.html', {'post_form': post_form})
def p_delete(request, post_id):
post = Post.objects.get(id=post_id)
post.delete()
return redirect('posts:list')
def p_update(request, post_id):
post = get_object_or_404(Post, id=post_id)
if request.method == 'POST':
postform = PostForm(request.POST, instance=post)
if postform.is_valid():
postform.save()
return redirect('posts:list')
else:
postform = PostForm(instance=post)
return render(request, 'create.html', {'post_form': postform})
마지막으로 list.html
파일을 수정하여 수정버튼을 붙이면 됩니다.
End.
Python 강좌는 아래의 책과 사이트를 참조했습니다. 조금 더 자세한 사항을 알고 싶으시면 해당 사이트를 방문하세요!!
- Python Official HomePage
- 점프 투 파이썬 - 이지스 퍼블리싱
- 전문가를 위한 파이썬(Fluent Python) - 한빛미디어
- 파이썬 웹 프로그래밍 - 한빛미디어
- 이미지 출처 : Designed by rawpixel.com / Freepik