Django Project ToDoList - 4

Page content

개요

  • Django 한 그릇 뚝딱 교재의 내용에서 멀티캠퍼스 강의에 맞게 일부 수정함
  • 2019년 버전이고 현재는 2023년이기 때문에 소스코드 변경 사항이 필요할 거 같아서 글을 남김

교재 홍보

Untitled

Step 01 - 이전 내용 확인

Step 02 - 남은 과제

  • 사용자가 입력한 문자열을 데이터베이스에 저장하기
  • DB에 저장된 내용을 보여 주기

Step 03 - 모델에 데이터 저장

  • 먼저, my_to_do_app 폴더에 있는 [views.py](http://views.py) 파일에서 model을 사용하려면 [models.py](http://models.py) 파일을 불러와야 한다.

    • 기존
    from django.shortcuts import render
    from django.http import HttpResponse
    
    # Create your views here.
    # before
    '''
    def index(request):
       return HttpResponse("My_to_do_app first page")
    '''
    
    # after
    def index(request):
        return render(request, "my_to_do_app/index.html")
    
    def createTodo(request):
        user_input_str = request.POST['todoContent']
        return HttpResponse("create Todo를 할 거야! => " + user_input_str)
    
    • 수정
      • from .models import * 코드는 [models.py](http://models.py) 에 있는 모든 것을 가져오겠다는 걸 의미
      • new_todoTodo 클래스를 활용하요 새로운 데이터를 생성하는 것을 의미
      • new_todo.save()DB에 저장하는 것을 의미한다.
    from django.shortcuts import render
    from django.http import HttpResponse
    from .models import * 
    
    # Create your views here.
    # before
    '''
    def index(request):
       return HttpResponse("My_to_do_app first page")
    '''
    
    # after
    def index(request):
        return render(request, "my_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 HttpResponse("create Todo를 할 거야! => " + user_input_str)
    

Step 04 - 쿼리 확인

  • 코드를 수정 후, runserver 를 재구동하여 DB에 데이터가 저장되는지 확인한다.

Untitled

  • 이번에는 dbshell에 접근한다.
$ python manage.py dbshell
SQLite version 3.39.3 2022-09-05 11:02:23
Enter ".help" for usage hints.
sqlite> SELECT * FROM my_to_do_app_Todo;

Untitled

  • DB에 정상적으로 데이터가 들어간 것을 확인할 수 있다.

Step 05 - 작성 후, 메인 페이지로 다시 돌아가기

  • 함수에서 처리를 진행한 이후, 메인 페이지로 돌아가려면, 다시 메인 페이지의 url 로 돌아가게 해야 한다.
  • Django에서는 HttpResponseRedirect함수를 이용한다.

urls.py 수정

  • [urls.py](http://urls.py) 파일에서 각 path의 뒷 부분에 name값을 추가한다.

    • 기존
    # -*- coding:utf-8 -*-
    # my_to_do_app > urls.py
    
    from django.urls import path 
    from . import views 
    
    urlpatterns = [
        path('', views.index), 
        path('createTodo/', views.createTodo)
    ]
    
    • 수정
    # -*- coding:utf-8 -*-
    # my_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 수정

  • 이번에는 my_to_do_app 폴더에 있는 [views.py](http://views.py) 파일을 수정한다.

    • 기존
    from django.shortcuts import render
    from django.http import HttpResponse
    from .models import * 
    
    # Create your views here.
    # before
    '''
    def index(request):
       return HttpResponse("My_to_do_app first page")
    '''
    
    # after
    def index(request):
        return render(request, "my_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 HttpResponse("create Todo를 할 거야! => " + user_input_str)
    
    • 수정
      • HttpResponseRedirect(reverse('index')) 함수를 통해 index라는 이름의 url 를 찾게 된다.
      • todos = Todo.objects.all() : DB에 있는 모든 데이터를 가져오는 것을 말한다.
      • content = {'todos' : todos} : 저장된 데이터를 todos key값에 할당한다.
      • render() 함수의 두번째 인자로 content를 넘겨준다. 그러면 index.html 파일에서 해당 딕셔너리를 활용할 수 있다.
    from django.shortcuts import render
    from django.http import HttpResponse, HttpResponseRedirect
    from django.urls import reverse
    from .models import * 
    
    # Create your views here.
    # before
    '''
    def index(request):
       return HttpResponse("My_to_do_app first page")
    '''
    
    # after
    def index(request):
        todos = Todo.objects.all()
        content = {'todos' : todos}
        return render(request, "my_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'))
    

index.html 파일 수정

  • 해당 데이터를 불러와서 처리할 수 있도록 반복문으로 처리한다.

    • 기존
               <div class="toDoDiv">
                    <ul class="list-group">
    
                        <form action="" method="GET">
                            <div class="input-group" name='todo1'>
                                <li class="list-group-item">메모한 내용은 여기에 기록될 거에요</li>
                                <input type="hidden" id="todoNum" name="todoNum" value="1"></input>
                                <span class="input-group-addon">
                                    <button type="submit" class="custom-btn btn btn-danger">완료</button>
                                </span>
                            </div>
                        </form>
                    </ul>
                </div>
    
    • 수정
      • {% for todo in todos %} 반복문의 for문과 같다. 템플릿 태그를 이용하면 html 파일 내부에서 파이썬 문법을 사용할 수 있다.
      • {{ todo.content }} 사용자에게 직접 보여 주는 값을 의미한다.
      • value="{{ todo.id }} 사용자에게 보여주지는 않지만, 추후 해당 id 를 이용해서 삭제할 때 보여준다.
          <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>

Untitled