본문 바로가기
Django

[Django] To Do List 만들기 (2) - HTML 템플릿, MVC 패턴

by 나룽나룽 2023. 7. 28.
이전 게시물에서는 Django 한그릇 뚝딱의 프로젝트 중
 
Chapter 2  To Do List의 프로젝트 구성, 앱 구성, URL 설정까지 완료했었다.

 

<이전 게시물 내용이 궁금하다면??>

https://data-analytics-nayoonee.tistory.com/3

 

하나의 URL을 통해 우리가 보여주려는 문자열을 보여주려했다면

이제는 HTML 템플릿과 MVC 패턴을 활용해 더욱 다양한 요소를 가져오고자 한다.

 

출처 YES24

1. HTML 템플릿 사용하기

HTML을 사용하기에 앞서 이전에 만든 앱에 template 라는 폴더를 만들고

폴더 안에 앱 이름과 동일한 폴더를 다시 만든 뒤, 그 안에 index.html을 만든다.

 

폴더 안에 폴더 안에 파일 주의

 

index.html에 들어가는 내용은 책에 나와있는 github 저장소 링크를 참조했다.

 

http://github.com/doorBW/Django_with_PracticeExamples 

 

잘 붙여넣었으면 사용자에게도 html 파일을 보여줄 수 있어야 한다.

그러기 위해 views.py에 들어가 return 내용을 아래와 같이 수정한다. 

 

from django.shortcuts import render
from django.http import HttpResponse

def index(request):
    return render(request, 'to_do_app/index.html')

 

 

그러고 동일하게 python manage.py runserver 해서 프로젝트를 돌리면

아래와 같은 화면이 나온다.

 

HTML을 적용한 ToDoList 첫 화면

 

2. MVC 따라하기 

그동안 우리는 장고에서 html 파일을 통해 우리가 원하는 화면을 보여주었고 그것을 위해 url을 설정했고

여러 함수를 활용해 사용자에게 html 파일을 화면으로 보여주었다.

 

이제부터 데이터를 사용하기 위해 어떤 데이터 베이스를 사용할 차례이다.

그러기 위해서 먼저 설정해주어야하는 것은 크게 2가지이다.

 

1. 어떠한 데이터베이스를 사용할 것인지 설정해주어야한다.

2. 테이블에 대한 형태를 정의해주어야한다. 

 

이번 장고에서는 기본으로 설정된 SQLite를 사용할거고

테이블의 형태는 models.py 에 하나의 모델을 만들어볼 것이다.

 

from django.db import models

# Create your models here.
class Todo(models.Model):
    content = models.CharField(max_length = 255)
    
# Todo 라는 클래스 이름은 곧 데이터베이스에서 테이블과 같음.
# 클래스 내부에 데이터 이름과 데이터 형태를 정의해둔 상태.

 

이렇게 models.py 내용을 수정했다면 이를 바탕으로 서버에

동일한 테이블을 데이터베이스에 만들어주어야 한다.

이를 위해 manage.py가 있는 위치로 이동,

아래의 명령어를 입력한다. 

 

python manage.py makemigrations
python manage.py migrate

 

이러면 migrations 파일들을 확인해서 데이터베이스에 적용되는데

정말 제대로 만들어졌는지 확인할 수 있도록 직접 데이터베이스에 접근할 수 있다.

하단의 명령어를 추가적으로 입력해서 테이블에 대한 정보를 확인할 수 있다.

 

python manage.py dbshell

# sqlite에 접속한 후,
.tables # 데이터베이스에 존재하는 테이블의 이름 출력
PRAGMA table_info(to_do_app.todo); # 데이터의 속성이 어떻게 만들어져있는지에 대한 설명 출력
select * from my to_do_app.todo;

 

select * from my to_do_app.todo; 까지 했을 때 아무것도 안 나온 것은 당연하다.

왜냐하면 아직까지는 어떻나 데이터를 테이블에 입력해두지 않은 상태이기 때문!

 

실제로 사용자가 텍스트를 입력하고 버튼을 눌렀을 때

해당 텍스트가 서버에 전송되도록 수정하기 위해서는

index.html 파일에 들어가 form 태그를 확인해야 한다.

 

form 태그의 액션은 서버로 데이터를 전달할 때 어떠한 url로 전달할지를 나타낸다. 

새로운 createTodo 라는 url로 보내도록 한다. 

<form action="./createTodo/" method="POST">{% csrf_token %}

 

이후 to_do_app 의 urls.py에도 createTodo에 대한 처리를 이어서 해준다. 

path('createTodo/', views.createTodo)

 

위의 언급한 createTodo 함수를 처리하도록 했기 때문에

사용자에게 어떤 화면이 보여지는지 처리해주는 view.py 에서 createTodo함수를 아래와 같이 만들어준다. 

from django.shortcuts import render
from django.http import HttpResponse

# Create your views here.

def index(request):
    return render(request, 'to_do_app/index.html')

def createTodo(request):
    return HttpResponse("create Todo를 할거야!")

 

이후 서버를 돌리면 아래와 같은 화면이 나온다.

위에처럼 createTodo 함수를 통해 문자열을 띄우긴 했지만 사실.. 우리의 목적은 이것이 아니라,

메모한 문자열을 받아와서 데이터베이스에 저장하는 것이어야한다. 

그러려면 아까 views.py에서 createTodo 함수를 다음과 같이 수정한다.

def createTodo(request):
    user_input_str = request.POST['todoContent'] # todoContent : html 태그 속성 중 name 값
    return HttpResponse("create Todo를 할거야! =>" +user_input_str)

 

그러면 필자가 입력한 '장고 복습하기' 라는 문자열을 받아서 출력할 수 있게 되었다.

 

 

이제 남은 과제는 2가지!

1. 사용자가 입력한 문자열을 출력한 것에 더해서 데이터베이스에 '저장하기'

2. 데이터베이스에 저장된 내용 '보여주기' 이다.

 

먼저 첫번째 과제를 해결하기 위해서는 DB와 관련된 models.py를 불려와야한다.

from .models import *

 

이어서 데이터베이스에 데이터를 추가하고 저장하기 위해

new_todo라는 새로운 변수를 활용한다.

수정된 views.py는 아래와 같다.

from django.shortcuts import render
from django.http import HttpResponse
from .models import *

# Create your views here.


def index(request):
    return render(request, 'to_do_app/index.html')

def createTodo(request):
    user_input_str = request.POST['todoContent']
    new_todo = Todo(content = user_input_str) # content 라는 값에 사용자가 입력한 값을 넣어주기
    new_todo.save() # 실제 데이터베이스에 저장하기
    return HttpResponse("create Todo를 할거야! =>" +user_input_str)

 

데이터가 잘 저장되는지 확인하려면,

터미널에 아래와 같이 입력해준다.

python manage.py dbshell
select * from to_do_app_todo;
테이블 내용 확인하기

 

이제는 메모에 입력한 내용이 createTodo/ 로 넘어가는 것이 아닌, 메인 페이지에 남도록 해야한다.

그러려면  to_do_app의 urls.py를 수정해야한다.

from django.urls import path
from . import views

urlpatterns = [
    path('', views.index, name='index'),
    path('createTodo/', views.createTodo, name='createTodo')
]

 

 이후 사용자의 화면에 보이도록 로직을 처리해주는 views.py로 이동해

다음과 같이 HttpResponseRedirect 함수와 reverse 함수를 import 하고 사용해준다.

views.py 의 수정본은 아래와 같다.

from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect # 메인페이지로 돌아가게 하는 HttpResponseRedirect 함수
from .models import *
from django.urls import reverse

# Create your views here.

def index(request):
    return render(request, 'to_do_app/index.html')

def createTodo(request):
    user_input_str = request.POST['todoContent']
    new_todo = Todo(content = user_input_str)
    new_todo.save()
    return HttpResponseRedirect(reverse('index'))
    return HttpResponse("create Todo를 할거야! =>" +user_input_str)

 

이처럼 views.py를 수정하면 메모하기를 입력하고 메인페이지로 오는 것은 성공,

그러나 입력한 내용이 하단에 '메모한 내용은 여기에 기록될 거예요'에 입력되지 않고 있다.

그동안 기록되고 있는 데이터베이스에 기록된 데이터를 보여주기 위해  views.py의  index함수를 수정해야한다.

from django.shortcuts import render
from django.http import HttpResponse, HttpResponseRedirect
from .models import *
from django.urls import reverse

# Create your views here.

def index(request):
    todos = Todo.objects.all()
    content = {'todos' : todos}
    return render(request, 'to_do_app/index.html', content)

def createTodo(request):
    user_input_str = request.POST['todoContent']
    new_todo = Todo(content = user_input_str)
    new_todo.save()
    return HttpResponseRedirect(reverse('index'))
    return HttpResponse("create Todo를 할거야! =>" +user_input_str)

 

이후 사용자의 화면에도 보여질 수 있게 index.html 파일을 다음과 같이 수정한다. 

<div class="toDoDiv">
                <ul class="list-group">
                    {% for todo in todos %}
                    <form action="" method="GET">
                        <div class="input-group" name='todo1'>
                            <li class="list-group-item">{{ todo.content }}</li>
                            <input type="hidden" id="todoNum" name="todoNum" value="{{ todo.id }}"></input>
                            <span class="input-group-addon">
                                <button type="submit" class="custom-btn btn btn-danger">완료</button>
                            </span>
                        </div>
                    </form>
                    {% endfor %}
                </ul>
            </div>

 

이렇게 코드를 수정해서 다시 메인페이지를 새로고침하면

Todo를 입력한 곳 하단에 그동안 입력한 데이터가 보이고, 새롭게 todo를 입력하면 제일 하단에 추가된다.

사용자에게 보여지는 데이터, 직접 todo 입력 후 첫화면에 내용 저장까지 모두 완료!

이렇게만 하면 앞서 언급한 과제 2가지

1. 사용자가 입력한 문자열을 출력한 것에 더해서 데이터베이스에 '저장하기'

2. 데이터베이스에 저장된 내용 '보여주기'

 

모두 성공적으로 완료한 셈이다!

 

완료한 todo가 사라지도록 하는 것은 다음 파트 CRUD 따라하기에서 다루고자한다.

 

to be continue...

 


 

GitHub - doorBW/Django_with_PracticeExamples: "실전 예제로 배우는 Django" 서적에 대한 예제 문제들 및 코드

"실전 예제로 배우는 Django" 서적에 대한 예제 문제들 및 코드를 포함하고 있는 repository 입니다. - GitHub - doorBW/Django_with_PracticeExamples: "실전 예제로 배우는 Django" 서적에 대한 예제 문제들 및 코드

github.com

 

 

[Django 한 그릇 뚝딱] To Do List 만들기 (1)

본 글은 파이썬 웹 프로그래밍을 단련하기 위해 도서의 프로젝트를 연습하고 기록한 글이다. 코드를 해석하기도 하지만 코드를 입력하는 흐름을 이해하고 중간 중간 진행하면서 막히는 에러 부

data-analytics-nayoonee.tistory.com