Django 구현 기초-Todo List 웹서비스
1. Todo List 웹서비스 시작하기 코드출처: 백엔드를 위한 Django REST Framework with 파이썬(영진닷컴) 1.1 프로젝트 기능 정리 Todo List 전체 조회하기 Todo List 상세 조회하기 Todo 생성하기 Todo 수정하기데이터 수정을 위한 Form 필요 Todo 생성용 Form 활용 가능 Todo 완료 처리하기 1.2 프로젝트 생성 python -m venv django_todolist
cd todolist
source ./bin/activate
# Windows의 경우: ./Scripts/activate
pip install django
python -m django --version
python --version
django-admin startproject todoweb .
python manage.py startapp todolist
python manage.py runserver
1.3 프로젝트 설정 #//file: "./todoweb/settings.py"
INSTALLED_APPS = [
'django.contrib.admin' ,
'django.contrib.auth' ,
'django.contrib.contenttypes' ,
'django.contrib.sessions' ,
'django.contrib.messages' ,
'django.contrib.staticfiles' ,
'todolist' , # 추가할 것
]
TIME_ZONE = 'Asia/Seoul' # 시간대를 한국으로 바꿀 것
#//file: "./todoweb/urls.py"
from django.contrib import admin
from django.urls import path
urlpatterns = [
path ( 'admin/' , admin . site . urls ),
]
python manage.py createsuperuser
1.4 Todo 모델 생성 #//file: "./todolist/models.py"
from django.db import models
# Create your models here.
class Todo ( models . Model ):
title = models . CharField ( max_length = 100 )
description = models . TextField ( blank = True )
created = models . DateTimeField ( auto_now_add = True )
complete = models . BooleanField ( default = False )
important = models . BooleanField ( default = False )
def __str__ ( self ):
return self . title
python manage.py makemigrations
python manage.py migrate
#//file: "./todolist/admin.py"
from django.contrib import admin
from todolist.models import Todo
# Register your models here.
admin . site . register ( Todo )
2. Todo 전체 조회 기능 만들기 2.1 Todo 전체 조회 기능 컨셉 첫 페이지에서 Todo List를 보여줌 완료되지 않은 항목만 보여줌 2.2 Bootstrap으로 좀 더 멋진 템플릿 만들기 Bootstrap웹 개발을 쉽게 할 수 있도록 도와주는 HTML, CSS, JavaScript 프레임워크 Twitter의 개발자들이 처음 만들었으며, 현재는 오픈 소스로 제공 중 특징반응형 디자인: 다양한 기기(모바일, 태블릿, 데스크탑)에서 잘 작동하도록 설계됨 미리 정의된 스타일: 버튼, 폼, 네비게이션 바 등 다양한 UI 요소에 대한 스타일 제공 확장성: 필요에 따라 커스터마이징이 가능하며, 다양한 플러그인과 함께 사용할 수 있음 CDN 지원: 별도의 설치 없이 CDN 링크를 통해 쉽게 사용할 수 있음 2.3 Todo 전체 조회 템플릿 만들기 <!--//file: "./todolist/templates/todo_list.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> TODO 목록 앱</h1>
<p>
<a href= "" ><i class= "bi-plus" ></i> Add Todo</a>
<a href= "" class= "btn btn-primary" style= "float:right" > 완료한 TODO 목록</a>
</p>
<ul class= "list-group" >
<li class= "list-group-item" >
<a href= "" > { { todo.title }}</a>
<div style= "float:right" >
<a href= "" class= "btn btn-danger" > 완료</a>
<a href= "" class= "btn btn-outline-primary" > 수정하기</a>
</div>
</li>
<li class= "list-group-item" >
<a href= "" > { { todo.title }}</a>
<span class= "badge badge-danger" > !</span>
<div style= "float:right" >
<a href= "" class= "btn btn-danger" > 완료</a>
<a href= "" class= "btn btn-outline-primary" > 수정하기</a>
</div>
</li>
<li class= "list-group-item" >
<a href= "" > { { todo.title }}</a>
<div style= "float:right" >
<a href= "" class= "btn btn-danger" > 완료</a>
<a href= "" class= "btn btn-outline-primary" > 수정하기</a>
</div>
</li>
</ul>
</body>
</div>
</html>
2.4 Todo 전체 조회 뷰 만들기 #//file: "./todolist/views.py"
from django.shortcuts import render , redirect
from todolist.models import Todo
def todo_list ( request ):
todos = Todo . objects . filter ( complete = False )
return render ( request , 'todolist/todo_list.html' , { 'todos' : todos })
2.5 Todo 전체 조회 템플릿 수정하기 <!--//file: "./todolist/templates/todo_list.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> TODO 목록 앱</h1>
<p>
<a href= "" ><i class= "bi-plus" ></i> Add Todo</a>
<a href= "" class= "btn btn-primary" style= "float:right" > 완료한 TODO 목록</a>
</p>
<ul class= "list-group" >
{ % for todo in todos %}
<li class= "list-group-item" >
<a href= "" > { { todo.title }}</a>
{ % if todo.important %}
<span class= "badge badge-danger" > !</span>
{ % endif %}
<div style= "float:right" >
<a href= "" class= "btn btn-danger" > 완료</a>
<a href= "" class= "btn btn-outline-primary" > 수정하기</a>
</div>
</li>
{ % endfor %}
</ul>
</body>
</div>
</html>
2.6 Todo 전체 조회 URL 연결하기 #//file: "./todolist/urls.py"
from django.urls import path
from . import views
urlpatterns = [
path ( '' , views . todo_list , name = 'todo_list' ),
]
#//file: "./todoweb/urls.py"
from django.contrib import admin
from django.urls import path , include
urlpatterns = [
path ( 'admin/' , admin . site . urls ),
path ( 'todolist/' , include ( 'todolist.urls' )),
]
3. Todo 상세 조회 기능 만들기 3.1 Todo 상세 조회 기능 컨셉 Todo List에서 Todo를 선택했을 때 조회 Todo의 제목과 설명을 보여줌 3.2 Todo 상세 조회 템플릿 만들기 <!--//file: "./todolist/templates/todo_detail.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> TODO 상세보기</h1>
<div class= "container" >
<div class= "row" >
<div class= "col-md-12" >
<div class= "card" >
<div class= "card-body" >
<h5 class= "card-title" > { { todo.title }}</h5>
</h5>
<p class= "card-text" > { { todo.description }}</p>
<a href= "{ % url 'todo_list' %}" class= "btn btn-primary" > 목록으로</a>
</div>
</div>
</div>
</div>
</div>
</body>
</div>
</html>
3.3 Todo 상세 조회 뷰 만들기 #//file: "./todolist/views.py"
from django.shortcuts import render , redirect
from .models import Todo
def todo_list ( request ):
todos = Todo . objects . filter ( complete = False )
return render ( request , 'todolist/todo_list.html' , { 'todos' : todos })
def todo_detail ( request , pk ):
todo = Todo . objects . get ( id = pk )
return render ( request , 'todolist/todo_detail.html' , { 'todo' : todo })
3.4 Todo 전체 조회 템플릿 수정하기 <!--//file: "./todolist/templates/todo_list.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> TODO 목록 앱</h1>
<p>
<a href= "" ><i class= "bi-plus" ></i> Add Todo</a>
<a href= "" class= "btn btn-primary" style= "float:right" > 완료한 TODO 목록</a>
</p>
<ul class= "list-group" >
{ % for todo in todos %}
<li class= "list-group-item" >
<a href= "{ % url 'todo_detail' pk=todo.pk %}" > { { todo.title }}</a>
{ % if todo.important %}
<span class= "badge badge-danger" > !</span>
{ % endif %}
<div style= "float:right" >
<a href= "" class= "btn btn-danger" > 완료</a>
<a href= "" class= "btn btn-outline-primary" > 수정하기</a>
</div>
</li>
{ % endfor %}
</ul>
</body>
</div>
</html>
3.5 Todo 상세 조회 URL 연결하기 #//file: "./todolist/urls.py"
from django.urls import path
from . import views
urlpatterns = [
path ( '' , views . todo_list , name = 'todo_list' ),
path ( '<int:pk>/' , views . todo_detail , name = 'todo_detail' ),
]
4. Todo 생성 기능 만들기 4.1 Todo 생성 기능 컨셉 제목, 설명, 중요도 입력 Form 필요 → ./todolist/forms.py 4.2 Todo 생성 템플릿 만들기 #//file: "./todolist/forms.py"
from django import forms
from .models import Todo
class TodoForm ( forms . ModelForm ):
class Meta :
model = Todo
fields = ( 'title' , 'description' , 'important' )
4.2.2 템플릿 만들기 <!--//file: "./todolist/templates/todo_post.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> TODO 추가하기</h1>
<div class= "container" >
<div class= "row" >
<div class= "col-md-12" >
<div class= "card" >
<div class= "card-body" >
<form method= "POST" >
{ % csrf_token %} { { form.as_p }}
<button type= "submit" class= "btn btn-primary" > 등록</button>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</div>
</html>
4.3 Todo 생성 뷰 만들기 #//file: "./todolist/views.py
from django.shortcuts import render , redirect
from .models import Todo
from .forms import TodoForm
def todo_list ( request ):
todos = Todo . objects . filter ( complete = False )
return render ( request , 'todolist/todo_list.html' , { 'todos' : todos })
def todo_detail ( request , pk ):
todo = Todo . objects . get ( id = pk )
return render ( request , 'todolist/todo_detail.html' , { 'todo' : todo })
def todo_post ( request ):
if request . method == "POST" :
form = TodoForm ( request . POST )
if form . is_valid ():
todo = form . save ( commit = False )
todo . save ()
return redirect ( 'todo_list' )
else :
form = TodoForm ()
return render ( request , 'todolist/todo_post.html' , { 'form' : form })
4.4 Todo 전체 조회 템플릿 수정하기 <!--//file: "./todolist/templates/todo_list.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> TODO 목록 앱</h1>
<p>
<a href= "{ % url 'todo_post' %}" ><i class= "bi-plus" ></i> Add Todo</a>
<a href= "" class= "btn btn-primary" style= "float:right" > 완료한 TODO 목록</a>
</p>
<ul class= "list-group" >
{ % for todo in todos %}
<li class= "list-group-item" >
<a href= "{ % url 'todo_detail' pk=todo.pk %}" > { { todo.title }}</a>
{ % if todo.important %}
<span class= "badge badge-danger" > !</span>
{ % endif %}
<div style= "float:right" >
<a href= "" class= "btn btn-danger" > 완료</a>
<a href= "" class= "btn btn-outline-primary" > 수정하기</a>
</div>
</li>
{ % endfor %}
</ul>
</body>
</div>
</html>
4.5 Todo 생성 URL 연결하기 #//file: "./todolist/urls.py"
from django.urls import path
from . import views
urlpatterns = [
path ( '' , views . todo_list , name = 'todo_list' ),
path ( '<int:pk>/' , views . todo_detail , name = 'todo_detail' ),
path ( 'post/' , views . todo_post , name = 'todo_post' ),
]
5. Todo 수정 기능 만들기 5.1 Todo 수정 기능 컨셉 Todo 생성 기능과 거의 동일 선택된 Todo의 내용이 Form에 미리 입력되어 있음 5.2 Todo 수정 뷰 만들기 #//file: "./todolist/views.py"
from django.shortcuts import render , redirect
from .models import Todo
from .forms import TodoForm
def todo_list ( request ):
todos = Todo . objects . filter ( complete = False )
return render ( request , 'todolist/todo_list.html' , { 'todos' : todos })
def todo_detail ( request , pk ):
todo = Todo . objects . get ( id = pk )
return render ( request , 'todolist/todo_detail.html' , { 'todo' : todo })
def todo_post ( request ):
if request . method == "POST" :
form = TodoForm ( request . POST )
if form . is_valid ():
todo = form . save ( commit = False )
todo . save ()
return redirect ( 'todo_list' )
else :
form = TodoForm ()
return render ( request , 'todolist/todo_post.html' , { 'form' : form })
def todo_edit ( request , pk ):
todo = Todo . objects . get ( id = pk )
if request . method == "POST" :
form = TodoForm ( request . POST , instance = todo )
if form . is_valid ():
todo = form . save ( commit = False )
todo . save ()
return redirect ( 'todo_list' )
else :
form = TodoForm ( instance = todo )
return render ( request , 'todolist/todo_post.html' , { 'form' : form })
5.4 Todo 전체 조회 템플릿 수정하기 <!--//file: "./todolist/templates/todo_list.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> TODO 목록 앱</h1>
<p>
<a href= "{ % url 'todo_post' %}" ><i class= "bi-plus" ></i> Add Todo</a>
<a href= "" class= "btn btn-primary" style= "float:right" > 완료한 TODO 목록</a>
</p>
<ul class= "list-group" >
{ % for todo in todos %}
<li class= "list-group-item" >
<a href= "{ % url 'todo_detail' pk=todo.pk %}" > { { todo.title }}</a>
{ % if todo.important %}
<span class= "badge badge-danger" > !</span>
{ % endif %}
<div style= "float:right" >
<a href= "" class= "btn btn-danger" > 완료</a>
<a href= "{ % url 'todo_edit' pk=todo.pk %" class= "btn btn-outline-primary" > 수정하기</a>
</div>
</li>
{ % endfor %}
</ul>
</body>
</div>
</html>
5.4 Todo 수정 URL 연결하기 #//file: "./todolist/urls.py"
from django.urls import path
from . import views
urlpatterns = [
path ( '' , views . todo_list , name = 'todo_list' ),
path ( '<int:pk>/' , views . todo_detail , name = 'todo_detail' ),
path ( 'post/' , views . todo_post , name = 'todo_post' ),
path ( '<int:pk>/edit/' , views . todo_edit , name = 'todo_edit' ),
]
6. Todo 완료 기능 만들기 6.1 Todo 완료 기능 컨셉 완료 버튼을 눌렀을 때 Todo의 complete 값을 True로 설정 완료 Todo 조회 기능: 완료된 Todo List만 보여줌 6.2 Todo 완료 템플릿 만들기 <!--//file: "./todolist/templates/done_list.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> DONE 목록</h1>
<p>
<a href= "{ % url 'todo_list' %}" class= "btn btn-primary" > 홈으로</a>
</p>
<ul class= "list-group" >
{ % for done in dones %}
<li class= "list-group-item" >
<a href= "{ % url 'todo_detail' pk=done.pk %}" > { { done.title }}</a>
{ % if done.important %}
<span class= "badge badge-danger" > !</span>
{ % endif %}
</li>
{ % endfor %}
</ul>
</body>
</div>
</html>
6.3 Todo 전체 조회 템플릿 수정하기 <!--//file: "./todolist/templates/todo_list.html"-->
<html>
<head>
<title> TODO 목록 앱</title>
<link
rel= "stylesheet"
href= "https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0/css/bootstrap.min.css"
/>
<link rel= "stylesheet" href= "https://cdn.jsdelivr.net/npm/bootstrap-icons@1.7.1/font/bootstrap-icons.css" >
</head>
<body>
<div class= "container" >
<h1> TODO 목록 앱</h1>
<p>
<a href= "{ % url 'todo_post' %}" ><i class= "bi-plus" ></i> Add Todo</a>
<a href= "{ % url 'done_list' %}" class= "btn btn-primary" style= "float:right" > 완료한 TODO 목록</a>
</p>
<ul class= "list-group" >
{ % for todo in todos %}
<li class= "list-group-item" >
<a href= "{ % url 'todo_detail' pk=todo.pk %}" > { { todo.title }}</a>
{ % if todo.important %}
<span class= "badge badge-danger" > !</span>
{ % endif %}
<div style= "float:right" >
<a href= "{ % url 'todo_done' pk=todo.pk %}" class= "btn btn-danger" > 완료</a>
<a href= "{ % url 'todo_edit' pk=todo.pk %}" class= "btn btn-outline-primary" > 수정하기</a>
</div>
</li>
{ % endfor %}
</ul>
</body>
</div>
</html>
6.4 Todo 완료 뷰 만들기 #//file: "./todolist/views.py"
from django.shortcuts import render , redirect
from .models import Todo
from .forms import TodoForm
def todo_list ( request ):
todos = Todo . objects . filter ( complete = False )
return render ( request , 'todolist/todo_list.html' , { 'todos' : todos })
def todo_detail ( request , pk ):
todo = Todo . objects . get ( id = pk )
return render ( request , 'todolist/todo_detail.html' , { 'todo' : todo })
def todo_post ( request ):
if request . method == "POST" :
form = TodoForm ( request . POST )
if form . is_valid ():
todo = form . save ( commit = False )
todo . save ()
return redirect ( 'todo_list' )
else :
form = TodoForm ()
return render ( request , 'todolist/todo_post.html' , { 'form' : form })
def todo_edit ( request , pk ):
todo = Todo . objects . get ( id = pk )
if request . method == "POST" :
form = TodoForm ( request . POST , instance = todo )
if form . is_valid ():
todo = form . save ( commit = False )
todo . save ()
return redirect ( 'todo_list' )
else :
form = TodoForm ( instance = todo )
return render ( request , 'todolist/todo_post.html' , { 'form' : form })
def done_list ( request ):
dones = Todo . objects . filter ( complete = True )
return render ( request , 'todo/done_list.html' , { 'dones' : dones })
def todo_done ( request , pk ):
todo = Todo . objects . get ( id = pk )
todo . complete = True
todo . save ()
return redirect ( 'todo_list' )
6.5 Todo 완료 URL 연결하기 #//file: "./todolist/urls.py"
from django.urls import path
from . import views
urlpatterns = [
path ( '' , views . todo_list , name = 'todo_list' ),
path ( '<int:pk>/' , views . todo_detail , name = 'todo_detail' ),
path ( 'post/' , views . todo_post , name = 'todo_post' ),
path ( '<int:pk>/edit/' , views . todo_edit , name = 'todo_edit' ),
path ( 'done/' , views . done_list , name = 'done_list' ),
path ( 'done/<int:pk>/' , views . todo_done , name = 'todo_done' ),
]
© 2020. AiDALab Co. All rights reserved. LICENSE | NOTICE | CHANGELOG
Powered by Hydejack v9.2.1