Search
Duplicate

Todo List

ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ

ํ”„๋กœ์ ํŠธ ์ƒ์„ฑ

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
๋ณต์‚ฌ