TITEDIOS 편한 코딩

[Django] Extra Study #2 - To-Do 리스트 웹 앱 만들기 본문

Django

[Django] Extra Study #2 - To-Do 리스트 웹 앱 만들기

TitediosKW 2024. 12. 6. 19:00
반응형

목차

  1. 뷰 구성
  2. 템플릿 작성
  3. 스타일 추가 (선택)
  4. 확장 가능성
  5. 결론

이전에 To-Do 리스트 웹 앱을 만드는 실습 했습니다. 프로젝트를 생성하고 모델 설계, 관리자 인터페이스 구성 및 URL 구성까지 코드를 작성하였습니다. 이제 나머지 기능에 대해 특히 뷰(View)에 대한 구현에 집중해서 진행해 보겠습니다.


1. 뷰 구성

View에서는 어떤 동작을 해야할까요? 천천히 생각해 봅시다. 가장 먼저 요구사항을 확인해야 합니다. 요구사항은 아래와 같습니다.

  • 핵심 기능:
    • 할 일 추가/수정/삭제/완료 표시
    • 완료된 항목과 미완료 항목 구분
    • 마감 기한 설정 및 정렬

그렇다면 이 중 View에서 할 일은 할 일 추가/수정/삭제/완료 표시 일 것입니다. 이 중 추가/수정/삭제에 대한 기능을 구현해보겠습니다. todo/views.py 파일을 아래와 같이 수정해봅니다.

from django.shortcuts import render, redirect, get_object_or_404
from .models import Task

def todo_list(request):
    tasks = Task.objects.all()
    return render(request, 'todo/todo_list.html', {'tasks': tasks})

def todo_add(request):
    if request.method == 'POST':
        title = request.POST.get('title')
        description = request.POST.get('description')
        Task.objects.create(title=title, description=description)
        return redirect('todo_list')
    return render(request, 'todo/todo_form.html')

def todo_edit(request, task_id):
    task = get_object_or_404(Task, id=task_id)
    if request.method == 'POST':
        task.title = request.POST.get('title')
        task.description = request.POST.get('description')
        task.completed = 'completed' in request.POST
        task.save()
        return redirect('todo_list')
    return render(request, 'todo/todo_form.html', {'task': task})

def todo_delete(request, task_id):
    task = get_object_or_404(Task, id=task_id)
    if request.method == 'POST':
        task.delete()
        return redirect('todo_list')
    return render(request, 'todo/todo_confirm_delete.html', {'task': task})
반응형

2. 템플릿 작성

이제 UI 인 템플릿을 작성해 보겠습니다. To-Do 리스트를 보여주고 생성하고 삭제하는 각각의 화면을 만들 예정입니다.

2.1 목록 템플릿

가장 먼저 Todo 리스트를 보여주는 화면을 만들어 보겠습니다. todo/templates/todo/todo_list.html 파일을 생성하고 아래와 같이 수정합니다.

<!DOCTYPE html>
<html>
<head>
    <title>To-Do List</title>
</head>
<body>
    <h1>To-Do List</h1>
    <a href="{% url 'todo_add' %}">Add New Task</a>
    <ul>
        {% for task in tasks %}
        <li>
            <strong>{{ task.title }}</strong>
            {% if task.completed %}<span>(Completed)</span>{% endif %}
            <br>
            <a href="{% url 'todo_edit' task.id %}">Edit</a> |
            <a href="{% url 'todo_delete' task.id %}">Delete</a>
        </li>
        {% endfor %}
    </ul>
</body>
</html>

 

간단한 코드 설명입니다.

  • {% url 'todo_add' %}: Django 템플릿 태그로, 지정된 URL 패턴의 이름(todo_add)에 해당하는 URL을 생성합니다. 예: /todo/add/와 같은 URL을 자동으로 생성.
  • {% for task in tasks %}... {% endfor %}: Django 템플릿 태그로, tasks라는 콘텍스트 변수를 반복(iterate)합니다. tasks는 Django 뷰에서 전달된 데이터(예: 할 일의 목록)로, 리스트나 쿼리 셋 형태일 가능성이 높습니다. 리스트에 있는 각 task 객체에 대해 <li> 요소를 생성합니다.
  • {% if task.completed %}: Django 템플릿의 조건문입니다. 각 할 일(task)의 completed 속성을 확인하여 완료된 경우 (Completed) 텍스트를 표시합니다.
  • {% url 'todo_edit' task.id %} 및 {% url 'todo_delete' task.id %}: todo_edit 및 todo_delete는 URL 패턴 이름입니다. task.id는 각각의 할 일 항목의 ID로, URL에서 사용할 수 있도록 동적으로 삽입됩니다. 예: /todo/edit/1/ 또는 /todo/delete/1/.

2.2 폼 템플릿

Todo 리스트를 추가하는 화면을 만들어 보겠습니다. todo/templates/todo/todo_form.html 파일을 생성하고 아래와 같이 작성합니다.

<!DOCTYPE html>
<html>
<head>
    <title>{% if task %}Edit Task{% else %}Add Task{% endif %}</title>
</head>
<body>
    <h1>{% if task %}Edit Task{% else %}Add Task{% endif %}</h1>
    <form method="post">
        {% csrf_token %}
        <label>Title:</label>
        <input type="text" name="title" value="{{ task.title|default:'' }}"><br>
        <label>Description:</label>
        <textarea name="description">{{ task.description|default:'' }}</textarea><br>
        {% if task %}
        <label>Completed:</label>
        <input type="checkbox" name="completed" {% if task.completed %}checked{% endif %}><br>
        {% endif %}
        <button type="submit">Save</button>
    </form>
    <a href="{% url 'todo_list' %}">Back to list</a>
</body>
</html>

 

이 템플릿도 간단하게 설명하겠습니다.

  • {% if task %}: task 객체가 존재하는 경우에 조건부로 코드 블록을 실행합니다.
  • {% else %}: if 조건이 거짓일 때 실행할 코드 블록입니다.
  • {% csrf_token %}: CSRF 보호 토큰을 출력합니다.
  • {{ task.title|default:'' }}: task 객체의 title 속성을 출력합니다. 만약 task 객체가 없거나 title 속성이 비어 있으면 빈 문자열을 출력합니다.

2.3 삭제 확인 템플릿

마지막으로 삭제를 할 수 있는 화면을 만들어 보겠습니다. todo/templates/todo/todo_confirm_elete.html 파일을 만들고 아래와 같이 작성해 보겠습니다.

<!DOCTYPE html>
<html>
<head>
    <title>Delete Task</title>
</head>
<body>
    <h1>Are you sure you want to delete "{{ task.title }}"?</h1>
    <form method="post">
        {% csrf_token %}
        <button type="submit">Yes, delete</button>
    </form>
    <a href="{% url 'todo_list' %}">Cancel</a>
</body>
</html>

 

간단한 코드 설명입니다.

  • {{ task.title }}: Django 템플릿 변수로, 뷰에서 전달된 task 객체의 title 속성을 표시합니다.
  • <button>... </button>: 이 버튼을 클릭하면 폼이 제출되고, Django 뷰에서 작업 삭제를 처리합니다.
  • {% url 'todo_list' %}: Django의 템플릿 태그로, todo_list라는 이름의 URL 패턴에 해당하는 경로를 생성합니다.
  • 사용자 행동과 결과
    a) 사용자가 "Yes, delete" 클릭: 브라우저는 서버로 POST 요청을 전송합니다. Django 뷰는 작업을 삭제한 후 사용자를 목록 페이지로 리디렉션 합니다.
    b) 사용자가 "Cancel" 클릭: 사용자는 삭제를 취소하고 목록 페이지(/todo/)로 돌아갑니다.

3. 실행 및 확장 가능성

3.1. 실행

이제 우리가 만든 Todo 리스트 웹 앱을 실행해 보겠습니다. 익숙한 명령어인 runserver 명령을 실행하겠습니다.

python manage.py runserver

 

이후에 lcoalhost:8000에 접속하면 아래와 같은 화면이 보일 것입니다. Task의 추가와 같은 작업을 해보시기 바라겠습니다.

To-Do 리스트 웹 앱 접속 초기 화면

3.2. 확장 가능성

이제까지 구현한 To-Do 리스트 웹 앱은 조금 더 기능을 확장할 수 있습니다. 아래와 같은 기능 확장에 대해서도 고민해 보시면 좋을 것 같습니다.

  • 사용자 인증 추가: 각 사용자마다 개별 To-Do 리스트 관리.
  • 완료된 항목 필터링: 완료된/미완료된 작업 분리.
  • REST API: Django REST Framework를 이용해 API로 확장.

결론

To-Do 리스트 웹 앱을 Django로 구현하며, 뷰(View) 구성과 템플릿 작성에 집중했습니다. 주요 뷰 함수는 할 일의 추가, 수정, 삭제, 목록 조회를 처리하며, 템플릿은 목록, 폼, 삭제 확인 화면으로 구성했습니다. 각 템플릿은 동적 데이터 표시와 사용자 인터페이스를 제공하며, CSRF 보호 및 URL 태그를 활용했습니다. 이 앱은 실행 후 localhost에서 작업을 테스트할 수 있으며, 사용자 인증, 완료 상태 필터링, REST API 확장 등으로 발전시킬 수 있습니다.

 

어떠신가요. 조금은 Django와 가까워지셨나요? 어떤 분은 여전히 낯설 수도 있고 조금 가까워지신 분도 있을 것입니다. 아직 조금 낯선 느낌이 드신다면 이전에 했던 실습들을 다시 한번 따라 하시면서 익숙해지시기를 바라겠습니다. 어떤 일을 익힌다는 것은 애석하게 지루한 연습 과정을 반복하는 것이 가장 빠른 길 같습니다. 이미 한 번 구현해 보신 것이기 때문에 지루하실 수 있지만 반복을 통해 더 많은 것을 익힐 수 있어다는 긍정적인 생각도 해볼 수 있을 것 같습니다.

 

궁금한 점이나 추가로 알고 싶은 내용이 있다면 댓글로 알려주세요!

 

도움이 되셨다면 공감 부탁드리겠습니다. 여러분의 공감이 정말 큰 힘이 됩니다.

 

감사합니다!

반응형