본문 바로가기

PYTHON-BACK

#파이썬 24일차_Django_개발환경/동작원리/실습2/Todo list웹 서비스 만들기

728x90

Todo List 웹서비스 만들기

1. Todo List 웹서비스 시작하기

1.1 프로젝트 기능 정리

  • Todo List 전체 조회하기
  • Todo List 상세 조회하기
  • Todo 생성하기
    • 데이터 입력을 위한 Form 필요
  • Todo 수정하기
    • 데이터 수정을 위한 Form 필요
    • Todo 생성용 Form 활용 가능
  • Todo 완료 처리하기

1.2 프로젝트 생성

  • 가상환경 설정
    • powershell 이용
python -m venv django_todolist
cd django_todolist
./Scripts/activate
pip install django
python -m django --version
python --version
  • Project 시작
django-admin startproject todoweb .
  • 앱 추가
python manage.py startapp todolist
  • 웹서버 실행
python manage.py runserver

 

1.3 프로젝트 설정

 

 

# ./photoweb/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'  # 타임존 변경

 

 

  • Migration 수행
python manage.py migrate
  • 계정 만들기
python manage.py createsuperuser

 

1.4 Todo 모델 생성

 

  • Model 만들기
# ./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
  • Model 적용시키기
python manage.py makemigrations
python manage.py migrate

 

Model을 Admin 페이지에 적용시키기

 

2. Todo 전체 조회 기능 만들기

 

2.1 Todo 전체 조회 기능 컨셉

 

 

  • 첫 페이지에서 Todo List를 보여줌
  • 완료되지 않은 항목만 보여줌
 

2.2 Bootstrap으로 좀 더 멋진 템플릿 만들기

 
  • Bootstrap
    • 웹 개발을 쉽게 할 수 있도록 도와주는 HTML, CSS, JavaScript 프레임워크
    • Twitter의 개발자들이 처음 만들었으며, 현재는 오픈 소스로 제공 중
    • 특징
      • 반응형 디자인: 다양한 기기(모바일, 태블릿, 데스크탑)에서 잘 작동하도록 설계됨
      • 미리 정의된 스타일: 버튼, 폼, 네비게이션 바 등 다양한 UI 요소에 대한 스타일 제공
      • 확장성: 필요에 따라 커스터마이징이 가능하며, 다양한 플러그인과 함께 사용할 수 있음
      • CDN 지원: 별도의 설치 없이 CDN 링크를 통해 쉽게 사용할 수 있음

2.3 Todo 전체 조회 뷰 만들기

# ./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, 'todo_list.html', {'todos': todos})

2.4 Todo 전체 조회 템플릿 만들기

todolist 내 templates 폴더 만들기

# ./todolist/templates/todo_list.html
 
<html>
    <head>
        <title>TODO LIST APP</title>
    </head>
    <body>
        <div class="container">
        <h1>TODO LIST APP</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>
        </div>
    </body>
</html>

2.6 Todo 전체 조회 URL 연결하기

# ./todolist/urls.py

from django.urls import path
from . import views

urlpatterns = [
    path("", views.todo_list, name='todo_list'),
]

 

# ./todoweb/urls.py

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path("", include('todolist.urls')),
]

 

http://127.0.0.1:8000/admin 에서 TODOLIST 제작

http://127.0.0.1:8000/admin 에서 TODOLIST 추가하기

 

http://127.0.0.1:8000 확인

3. Todo 상세 조회 기능 만들기

3.1 Todo 상세 조회 기능 컨셉

 

  • Todo List에서 Todo를 선택했을 때 조회
  • Todo의 제목과 설명을 보여줌

 

3.2 Todo 상세 조회 뷰 만들기

# ./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.3 Todo 상세 조회 템플릿 만들기

# ./todolist/templates/todo_detail.html

<html>
    <head>
        <title>TODO LIST APP</title>
    </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>
                                <p class="card-text">{{ todo.description }}</p>
                                <a href="{% url 'todo_list' %}" class="btn btn-primary">목록으로</a>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </body>
</html>

 

 

3.4 Todo 상세 조회 URL 연결하기

# ./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'),
]

 

3.5 Todo 전체 조회 템플릿 수정하기

  • 상세 조회 페이지로 들어오기 위한 링크 걸기
# ./todolist/templates/todo_list.html

<html>
  <head>
    <title>TODO 목록 앱</title>
    <link
      rel="stylesheet"
    />
  </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.id %}">{{ 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. Todo 생성 기능 만들기

 

4.1 Todo 생성 기능 컨셉

 

 

4.2.1 Todo 내용 입력을 위한 Form 만들기

# ./todolist/forms.py

from django import forms
from .models import Todo

class TodoForm(forms.ModelForm):
    class Meta:
        model = Todo
        fields = ('title', 'description', 'important')

4.3 Todo 생성 뷰 만들기

# ./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 생성 템플릿 만들기

# ./todolist/templates/todo_post.html

<html>
  <head>
    <title>TODO LIST APP</title>
  </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>
    </div>
  </body>
</html>
 

4.5 Todo 전체 조회 템플릿 수정하기

  • Todo 생성을 위한 링크 걸기
# ./todolist/templates/todo_list.html

<html>
  <head>
    <title>TODO 목록 앱</title>
    <link
      rel="stylesheet"
    />
  </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.6 Todo 생성 URL 연결하기

# ./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 수정 뷰 만들기

# ./todolist/views.py에 추가
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, 'todo_post.html', {'form': form})

5.4 Todo 전체 조회 템플릿 수정하기

Todo 수정을 위한 링크 걸기

# ./todolist/templates/todo_list.html

<html>
  <head>
    <title>TODO 목록 앱</title>
    <link
      rel="stylesheet"
    />
  </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 연결하기

# ./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.5 Todo 완료 URL 연결하기

# ./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'),
]

 

6.4 Todo 완료 뷰 만들기

# ./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.2 Todo 완료 템플릿 만들기

 
# ./todolist/templates/done_list.html
<html>
  <head>
    <title>TODO LIST APP</title>
  </head>
  <body>
    <div class="container">
      <h1>완료된 TODO 목록</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.id %}">{{ done.title }}</a>
          {% if done.important %}
            <span class="badge badge-danger">!</span>
          {% endif %}
        </li>
        {% endfor %}
      </ul>
    </div>
  </body>
</html>

 

6.3 Todo 전체 조회 템플릿 수정하기

 
  • Todo 완료를 위한 링크 걸기
# ./todolist/templates/todo_list.html

<html>
  <head>
    <title>TODO LIST APP</title>
  </head>
  <body>
    <div class="container">
      <h1>TODO LIST APP</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.id %}">{{ todo.title }}</a>
          {% if todo.important %}
          <span class="badge badge-danger">!</span>
          {% endif %}
          <div style="float:right">
            <a href="{% url 'todo_done' pk=todo.id %}" class="btn btn-danger">완료</a>
            <a href="{% url 'todo_edit' pk=todo.id %}" class="btn btn-outline-primary">수정하기</a>
          </div>
        </li>
        {% endfor %}
      </ul>
    </div>
  </body>
</html>

 

완료 버튼을 누르게 되면 완료된 TODO 목록으로 들어간다.

 

 

 

728x90

'PYTHON-BACK' 카테고리의 다른 글

#파이썬 27일차_MYSQL3  (0) 2024.08.07
#파이썬 26일차_MYSQL2  (0) 2024.08.06
#파이썬 23일차_Django_개발환경/동작원리/실습1  (0) 2024.07.31
#파이썬 22일차_Django  (0) 2024.07.30
#파이썬 22일차_GitHub Action  (0) 2024.07.30