νλ‘μ νΈ κ΅¬μ‘°
νλ‘μ νΈ μμ±
django-admin startproject todolist
cd todolist
Bash
볡μ¬
μ± μμ±
python manage.py startapp todo
Bash
볡μ¬
μ± λ±λ‘ (settings.py)
# Application definition
## todo μ± λ±λ‘
INSTALLED_APPS = [
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
'todo'
]
Python
볡μ¬
λͺ¨λΈ μ μ (models.py)
from django.db import models
# Create your models here.
class Todo(models.Model):
STATUS_CHOICE = [
('WAIT', 'λκΈ°'),
('ING', 'μ§ν'),
('DONE', 'μλ£')
]
no = models.AutoField(primary_key=True) # μλ μ¦κ° νλ(PK)
title = models.CharField(max_length=255)
status = models.CharField(
max_length=20,
choices=STATUS_CHOICE,
default='WAIT'
)
created_at = models.DateTimeField(auto_now_add=True)
updated_at = models.DateTimeField(auto_now=True)
def __str__(self):
return "{} : {}".format(self.title, self.status)
Python
볡μ¬
λ§μ΄κ·Έλ μ΄μ
# λ§μ΄κ·Έλ μ΄μ
νμΌ μμ±
python manage.py makemigrations
# λ§μ΄κ·Έλ μ΄μ
μ€ν
python manage.py migrate
Bash
볡μ¬
URL λ§€ν (urls.py)
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('todo', views.todo, name='todo'),
path('create', views.create, name='create'),
path('delete', views.delete, name='delete'),
path('ing', views.ing, name='ing'),
path('done', views.done, name='done'),
path('wait', views.wait, name='wait'),
]
Python
볡μ¬
View μ μ (views.py)
from django.shortcuts import render
from django.http import HttpResponseRedirect
from django.urls import reverse
from django.db.models import Q
from .models import * # models μ λͺ¨λ λͺ¨λΈ import
# Create your views here.
def index(request):
print('λ©μΈ νλ©΄...')
return render(request, 'todo/index.html', {})
def todo(request):
print('ν μΌ λͺ©λ‘ νλ©΄...')
# ν μΌ λͺ©λ‘ μ‘°ν
# Todo λͺ¨λΈμ λκΈ° λͺ©λ‘ μ‘°ν
wait_list = Todo.objects.filter(status='WAIT')
# Todo λͺ¨λΈμ μ§ν λͺ©λ‘ μ‘°ν
ing_list = Todo.objects.filter(Q(status='ING') | Q(status='DONE')).order_by('-status')
content = {'wait_list': wait_list, 'ing_list': ing_list}
# render(request, ν
νλ¦Ώ κ²½λ‘, λ°μ΄ν°{})
# - λ°μ΄ν°{} : ν
νλ¦Ώμ λ°μ΄ν°λ₯Ό μ λ¬
return render(request, 'todo/todo.html', content)
def create(request):
print('ν μΌ λ±λ‘...')
# POST λ°©μμ νλΌλ―Έν°
title = request.POST['title']
# λ±λ‘ μμ²
new_todo = Todo(title = title)
new_todo.save() # DBμ μ μ₯
# ν μΌ λͺ©λ‘(todo)μΌλ‘ 리λ€μ΄λ νΈ
return HttpResponseRedirect(reverse('todo'))
def delete(request):
print("μμ μμ²...")
# νλΌλ―Έν°
no = request.POST['no']
print('no : {}'.format(no))
try:
todo = Todo.objects.get(no=no)
todo.delete() # ν μΌ μμ μμ²
except Todo.DoesNotExist:
print('μμ ν ν μΌμ΄ μμ΅λλ€.')
return HttpResponseRedirect(reverse('todo'))
def ing(request):
print('μ§ν μνλ‘ λ³κ²½...')
no = request.POST['no']
print('no : {}'.format(no))
try:
todo = Todo.objects.get(no=no)
# ν μΌ μν μμ
todo.status = 'ING'
todo.save()
except Todo.DoesNotExist:
print('μμ ν ν μΌμ΄ μμ΅λλ€.')
return HttpResponseRedirect(reverse('todo'))
def done(request):
print('μλ£ μνλ‘ λ³κ²½...')
no = request.POST['no']
print('no : {}'.format(no))
try:
todo = Todo.objects.get(no=no)
# ν μΌ μν μμ
if todo.status == 'DONE':
todo.status = 'ING'
else:
todo.status = 'DONE'
todo.save()
except Todo.DoesNotExist:
print('μμ ν ν μΌμ΄ μμ΅λλ€.')
return HttpResponseRedirect(reverse('todo'))
def wait(request):
print('λκΈ° μνλ‘ λ³κ²½...')
no = request.POST['no']
print('no : {}'.format(no))
try:
todo = Todo.objects.get(no=no)
# ν μΌ μν μμ
todo.status = 'WAIT'
todo.save()
except Todo.DoesNotExist:
print('μμ ν ν μΌμ΄ μμ΅λλ€.')
return HttpResponseRedirect(reverse('todo'))
Python
볡μ¬
Template μμ±
βββ templates/
βββ todo/
β βββ index.html
β βββ todo.html
Plain Text
볡μ¬
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>λ©μΈ νλ©΄</title>
</head>
<body>
<h1>λ©μΈ νλ©΄</h1>
<h3>Hello Django~!</h3>
<a href="./todo">To Do List</a>
</body>
</html>
HTML
볡μ¬
todo.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>ν μΌ λͺ©λ‘</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4Q6Gf2aSP4eDXB8Miphtr37CMZZQ5oXLH2yaXMJ2w8e2ZtHTl7GptT4jmndRuHDT" crossorigin="anonymous">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.13.1/font/bootstrap-icons.min.css">
<style>
input[type='checkbox'] {
cursor: pointer;
}
</style>
</head>
<body>
<div class="container">
<div class="row justify-content-center">
<div class="col-12 col-md-8 col-lg-6">
<h1>ν μΌ λͺ©λ‘</h1>
<hr>
<form action="./create" method="post">
{% csrf_token %}
<div class="input-group mb-3">
<label for="todo" class="input-group-text">ν μΌ</label>
<input type="text" name="title" class="form-control" id="todo"
placeholder="ν μΌμ μ
λ ₯ν΄μ£ΌμΈμ."
autofocus
>
<button type="submit" class="btn btn-outline-primary">λ±λ‘</button>
</div>
</form>
<hr>
<h3>μ§ν λͺ©λ‘</h3>
<table class="table table-bordered text-center align-middle">
<thead>
<tr class="table-dark">
<th>β
</th>
<th class="text-start">ν μΌ</th>
<th>β</th>
</tr>
</thead>
<tbody>
{% for todo in ing_list %}
<tr {% if todo.status == 'DONE' %}class="table-success"{% endif %}>
<td>
<form action="./done" method="post">
{% csrf_token %}
<input type="hidden" name="no" value="{{ todo.no }}">
<input type="checkbox" class="form-check-input"
onchange="this.form.submit()"
{% if todo.status == 'DONE' %}checked{% endif %}>
</form>
</td>
<td class="text-start">
{{ todo.title }}
</td>
<td>
<div class="d-flex justify-content-center gap-2">
<form action="./wait" method="post">
{% csrf_token %}
<input type="hidden" name="no" value="{{ todo.no }}">
<button class="btn btn-success">
<i class="bi bi-arrow-down-square"></i>
</button>
</form>
<form action="./delete" method="post">
{% csrf_token %}
<input type="hidden" name="no" value="{{ todo.no }}">
<button class="btn btn-danger">
<i class="bi bi-trash2"></i>
</button>
</form>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="3" class="text-center text-muted">
μ‘°νλ λ°μ΄ν°κ° μμ΅λλ€.
</td>
</tr>
{% endfor %}
</tbody>
</table>
<hr>
<h3>λκΈ° λͺ©λ‘</h3>
<table class="table table-bordered text-center align-middle">
<thead>
<tr class="table-dark">
<th>β
</th>
<th class="text-start">ν μΌ</th>
<th>β</th>
</tr>
</thead>
<tbody>
{% for todo in wait_list %}
<tr>
<td>
<form action="./ing" method="post">
{% csrf_token %}
<input type="hidden" name="no" value="{{ todo.no }}">
<button type="submit" class="btn btn-outline-primary">
<i class="bi bi-arrow-up-square"></i>
</button>
</form>
</td>
<td class="text-start">
{{ todo.title }}
</td>
<td>
<form action="./delete" method="post">
{% csrf_token %}
<input type="hidden" name="no" value="{{ todo.no }}">
<button class="btn btn-danger">
<i class="bi bi-trash2"></i>
</button>
</form>
</td>
</tr>
{% empty %}
<tr>
<td colspan="3" class="text-center text-muted">
μ‘°νλ λ°μ΄ν°κ° μμ΅λλ€.
</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.6/dist/js/bootstrap.bundle.min.js" integrity="sha384-j1CDi7MgGQ12Z7Qab0qlWQ/Qqz24Gc6BM0thvEMVjHnfYGF0rmFCozFSxQBxwHKO" crossorigin="anonymous"></script>
</body>
</html>
HTML
볡μ¬