1. Model 생성
model 생성은 각 패키지의 models.py 파일에서 설정할 수 있다. 만들어두었던 accoutapp의 models.py에 아래와 같이 작성해본다.
accountapp/models.py
from django.db import models
# Create your models here.
class HelloWorld(models.Model):
text = models.CharField(max_length=255, null=False)
형태를 보면 DB에서 속성값을 정의하듯이 model을 정의한다. models.CharField로 문자열이 들어가는 필드를 정의하는데, 이름은 text, 길이는 255, nullable = false로 설정해주었다.
Migrations
'python manage.py makemigrations' 명령어를 입력하면 accoutnapp/migrations 내부에 0001_initial.py 파일이 생성된다. 이렇게 생성된 migrations 파일은 임의로 수정하거나 삭제하면 안된다. 필요 시 다른 명령어를 통해 수정해야한다.
'python manage.py migrate' 명령어를 입력하면 생성된 initial.py 파일이 실제 DB로 migrate 된다. 이때 django가 기본적으로 갖고 있는 admin, auth 정보들도 자동으로 같이 마이그레이션이 일어난다.
sqlite3
migrate한 정보는 루트 디렉토리의 db.sqlite3를 눌러 확인할 수 있다. pycharm에서는 우측 탭에서 Database 트리를 보여준다.
2. GET, POST 단순 요청 연습
form 태그
hello_world.html 에 form 태그로 서버에 요청할 내용을 작성한다.
{% extends 'base.html' %}
{% block content %}
<div style="height: 10rem; background-color:#38df81; border-radius: 1rem; margin: 2rem;">
testing
<form action="/account/hello_world/" method="post">
<input type="submit" class="btn btn-primary" value="POST"/>
</form>
</div>
{% endblock %}
CSRF 쿠키 처리
버튼을 눌러보면, CSRF 에러가 나온다. POST 요청을 보낼 때는 반드시 CSRF Token을 같이 보내주어야 한다.
이것은 django에서 제공하는 csrf token을 추가함으로써 기본적으로 해결할 수 있다. form 태그에 {% csrf_token %}을 입력해준다.
{% extends 'base.html' %}
...중략
<form action="/account/hello_world/" method="post">
{% csrf_token %}
<input type="submit" class="btn btn-primary" value="POST"/>
...중략
{% endblock %}
view 처리 : context , {{ }}
이제 POST 요청이 왔을 때 view에서 분기처리를 해보자. 기본적으로 url에 접근하는 것은 GET method이고, 버튼을 눌렀을 때는 동일 url로 POST method로 요청하므로 아래와 같이 view.py 파일을 분기처리 해준다.
여기서 context는 View에서 처리 후 Template 쪽으로 전달할 데이터 집합을 의미한다.
accountapp/view.py
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
def hello_world(request):
if request.method == 'POST':
return render(request, 'accountapp/hello_world.html', context={'text' : 'POST REQUEST'})
else:
return render(request, 'accountapp/hello_world.html', context={'text': 'GET REQUEST'})
context 내부 객체의 이름을 'text'로 지정했으므로, template 파일에서 {{ text }} 문법을 사용하여 렌더링해준다.
templates/accountapp/hello_world.html 일부
...생략
<form action="/account/hello_world/" method="post">
...중략
</form>
{{ text }}
</div>
요청 전/후 렌더링이 변화하는 것을 확인할 수 있다.
3. POST DB 연동 연습
요청-응답 구조 만들기
hello_world.html
서버로 데이터를 보내기 위해서 input 태그를 하나 넣는다. 서버에서는 받는 값을 name으로 인식한다.
{% extends 'base.html' %}
{% block content %}
<div style="border-radius: 1rem; margin: 2rem; text-align: center">
<h1 style="font-family: 'Noto Sans KR'">
helloworld list
</h1>
<form action="/account/hello_world/" method="post">
{% csrf_token %}
<div>
<input type="text" name="hello_world"/>
</div>
<input type="submit" class="btn btn-primary" value="POST"/>
</form>
{{ text }}
</div>
{% endblock %}
views.py
여기서 request.POST.get('{name}') 구문으로 post 요청, hello_world로 사용자로부터 입력된 값을 읽어들여서 {{ text }} 부분에 표시할 수 있게 된다.
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
def hello_world(request):
if request.method == 'POST':
get = request.POST.get('hello_world')
return render(request, 'accountapp/hello_world.html', context={'text' : get})
else:
return render(request, 'accountapp/hello_world.html', context={'text': 'GET REQUEST'})
객체 저장 및 전달
이제 models.py에서 migrate를 하여 만든 HelloWorld 객체(class)를 처리해본다.
views.py
request.POST.get으로 얻어온 사용자의 입력값을 HelloWorld 객체의 text값에 넣고 save()를 한다. 이렇게 하면 DB에 HelloWorld 객체가 저장된다. 렌더링 값도 new_hello_world로 변경해준다.
from django.http import HttpResponse
from django.shortcuts import render
# Create your views here.
from accountapp.models import HelloWorld
def hello_world(request):
if request.method == 'POST':
get = request.POST.get('hello_world')
new_hello_world = HelloWorld()
new_hello_world.text = get
new_hello_world.save()
return render(request, 'accountapp/hello_world.html', context={'new_hello_world' : new_hello_world.text})
else:
return render(request, 'accountapp/hello_world.html', context={'text': 'GET REQUEST'})
hello_world.html
{% extends 'base.html' %}
{% block content %}
<div style="border-radius: 1rem; margin: 2rem; text-align: center">
<h1 style="font-family: 'Noto Sans KR'">
helloworld list
</h1>
<form action="/account/hello_world/" method="post">
{% csrf_token %}
<div>
<input type="text" name="hello_world"/>
</div>
<input type="submit" class="btn btn-primary" value="POST"/>
</form>
{{ new_hello_world }} {# 변경 #}
</div>
{% endblock %}
DB에 실제로 값이 저장되었다.
if, for 구문 적용과 PRG(Post Redirect Get) 패턴 적용하기
if, for 구문을 적용하여 입력된 모든 값이 출력되도록 해본다.
views.py
PRG 패턴을 적용함에 따라 Post의 return 값을 HttpResponseRedirect로 변경한다. 이것은 POST에도 그냥 render() 메서드를 적용할 경우, 웹 페이지에서 POST를 누르고 새로고침을 하면 같은 POST 요청이 계속해서 반복해서 올 수 있기 때문이다. 따라서 POST 후 Redirect -> GET이 되도록 해준다. reverse 구문과 '{디렉토리, 메서드명'} 을 통해 '/account/hello_world/'라고 입력해야되는 부분을 작성하기 편하도록 변경해주었다.
또한 DB에 저장된 모든 객체를 불러오기 위해서 HelloWorld.objects.all() 메서드를 이용하였다.
from django.http import HttpResponse, HttpResponseRedirect
from django.shortcuts import render
# Create your views here.
from django.urls import reverse
from accountapp.models import HelloWorld
def hello_world(request):
if request.method == 'POST':
get = request.POST.get('hello_world')
new_hello_world = HelloWorld()
new_hello_world.text = get
new_hello_world.save()
return HttpResponseRedirect(reverse('accountapp:hello_world'))
else:
return render(request, 'accountapp/hello_world.html', context={'hello_world_list': HelloWorld.objects.all()})
hello_world.html의 일부
{% if ... %} {% endif %} 구문, {% for ... in ... %} {% endfor %} 구문으로 DB에서 불러온 HelloWorld 객체 리스트의 text 값을 반복적으로 출력한다.
{% if hello_world_list %}
{% for hello_world in hello_world_list %}
<h6>
{{ hello_world.text }}
</h6>
{% endfor %}
{% endif %}
DB에 입력된 값들이 반복적으로 출력되었다.
4. DEBUG 환경설정
서버 실행이나 디버깅을 하기 위해서 Ultimate 버전에서는 [Shift + F10/F9]를 눌러도 된다. 하지만 이 설정을 직접 하는 방법에 대해서도 참고로 알고 있자.
Run -> Edit Configuration에 들어가서 + 버튼을 눌러 Python을 추가한다.
script path를 venv/manage.py로 설정하고, Parameter를 runserver로 입력해주고 OK
이후 manage.py를 우클릭하여 Debug로 실행하면 서버가 실행되는 것을 확인할 수 있다.
참조
1. 작정하고 장고! Django로 Pinterest 따라만들기 : 바닥부터 배포까지-박형석님 인프런 강의
'Programming-[Backend] > Django' 카테고리의 다른 글
Django로 Pinterest 따라 만들기-6. BootStrap 추가, DetailView 구현 (0) | 2022.06.08 |
---|---|
Django로 Pinterest 따라 만들기-5. AccountApp : CBV, CreateView, Login, reverse_lazy (0) | 2022.06.08 |
Django로 Pinterest 따라 만들기-3. static, CSS 설정 (0) | 2022.06.07 |
Django로 Pinterest 따라 만들기-2.git 관리, HTML 구조 생성(include, extends, block) (0) | 2022.06.06 |
Django로 Pinterest 따라 만들기-1.프로젝트 생성 및 세팅, 기본 구조 만들어보기 (0) | 2022.06.06 |