화요일!
PyCharm으로 지난번에 했던 Project(MyFirstWeb_0215) 생성, Django 설치 및 MySQL 연동을 똑같이 진행했다.
1. 오늘은 templates 폴더 안에 추가로 polls 폴더를 만들고 index.html 파일을 생성해줌

2. HttpResponse 안에 질문을 클릭하면 question.id가 연결되도록 link 속성 지정하기

3. urls.py(polls URLConf) 파일에서 question_id에 대한 URLConf의 경로를 설정해야 함

4. polls App에 해당되는 URL로 진입(request)하면 view로 detail함수가 호출되므로 이를 정의해야 함

5. templates/polls 폴더 안에 detail라는 HTML 파일을 만들어줌

6. polls page에서 문제를 클릭면 해당하는 question_id(PK)에 따라 질문의 내용을 출력함

7. <input type="radio"> 버튼으로 선택 항목들 표현함
↓templates_polls_detail.html↓
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
질문 내용은 : {{ my_question.question_text }}
<br><br><br>
{#radio 버튼들을 name(그룹)으로 묶으면 한 개씩만 선택이 가능함#}
<input type="radio" name="choice">
<input type="radio" name="choice">아이유<br>
<input type="radio" name="choice">김연아<br>
<input type="radio" name="choice">홍길동<br>
<input type="radio" name="choice">신사임당<br>
{#radio 버튼과 우측의 텍스트 연결시키기#}
<input type="radio" name="choice" id="my_1">
<label for="my_1">아이유</label><br>
<input type="radio" name="choice" id="my_2">
<label for="my_2">김연아</label><br>
<input type="radio" name="choice" id="my_3">
<label for="my_3">홍길동</label><br>
<input type="radio" name="choice" id="my_4">
<label for="my_4">신사임당</label><br>
------------------------------------------------------------------------------
{#for문으로 반복하기#}
{% for choice in my_question.choice_set.all %}
<input type="radio" name="choice" id="my_{{ forloop.counter }}">
<label for="my_{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
</body>
</html>
8. 답변 등록 기능 만들기
<input type="submit">은 button type과 달리 서버로 답변 항목을 보냄
form으로 답변과 submit 버튼을 묶어서 action 속성으로 등록한 URL로 이동하게 만듦
↓templates_polls_detail.html↓
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
질문 내용은 : {{ my_question.question_text }}
<br><br><br>
{#form으로 답변과 submit 버튼을 묶어서 action 속성으로 등록한 URL로 이동하게 만듦#}
<form action="http://www.naver.com">
{% for choice in my_question.choice_set.all %}
<input type="radio" name="choice" id="my_{{ forloop.counter }}">
<label for="my_{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<br><br>
<input type="submit" value="투표하기">
</form>
</body>
</html>
9. POST 방식으로 서버에 답변 보냄
↓templates_polls_detail.html↓
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
질문 내용은 : {{ my_question.question_text }}
<br><br><br>
{#for문으로 반복하기 - GET 방식#}
<form action="http://www.naver.com" method="get">
{% for choice in my_question.choice_set.all %}
<input type="radio" name="choice"
id="my_{{ forloop.counter }}"
value={{ choice.id }}>
<label for="my_{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<br><br>
<input type="submit" value="투표하기">
</form>
----------------------------------------------------------------------------------
{#for문으로 반복하기 - POST 방식#}
<form action="http://www.naver.com" method="post">
{% for choice in my_question.choice_set.all %}
<input type="radio" name="choice"
id="my_{{ forloop.counter }}"
value={{ choice.id }}>
<label for="my_{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<br><br>
<input type="submit" value="투표하기">
</form>
</body>
</html>
10. 답변이 등록됨에 따라 POST 방식으로 action 속성의 URL로 이동하는 것이 아닌 투표수가 올라가야 하므로,
urls.py(polls URLConf) 파일에서 views.vote 함수에 대한 URLConf의 경로를 설정하고
from django.urls import path
from polls import views
app_name = 'polls'
urlpatterns = [
# http://127.0.0.1:80000/polls/
path('', views.index, name='index'),
# http://127.0.0.1:80000/polls/1~3/
path('<int:question_id>/', views.detail, name='detail'),
# http://127.0.0.1:80000/polls/1~3/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
]
11. polls 폴더의 views.py에서 vote 함수를 정의하고,
from django.shortcuts import render, get_object_or_404
from polls.models import Question
def index(request):
# 질문객체를 모두 가져와요!
question_list = Question.objects.all().order_by("-pub_date")
context = {
"q_list": question_list
}
return render(request, "polls/index.html", context)
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
context = {
"my_question": question
}
return render(request, "polls/detail.html", context)
def vote(request, question_id):
# 질문객체를 가져와요!
question = get_object_or_404(Question, pk=question_id)
# 해당 질문객체와 Foreign Key로 연결된 객체를 가져와요!
choice = question.choice_set.get(pk=request.POST['choice'])
choice.votes += 1
choice.save()
12. templates/polls 폴더 안 detail.html에서 내용을 입력함
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
질문 내용은 : {{ my_question.question_text }}
<br><br><br>
<form action="/polls/{{ my_question.id }}/vote/"
method="post">
{#보안 코드: form 엘리먼트를 통해 전송된 데이터(답변)이 실제로 웹 브라우저에서 작성된 것인지 판단하는 검사기 역할#}
{% csrf_token %}
{% for choice in my_question.choice_set.all %}
<input type="radio" name="choice"
id="my_{{ forloop.counter }}" {#for문이 반복되는 횟수를 셈#}
value="{{ choice.id }}">
<label for="my_{{ forloop.counter }}">{{ choice.choice_text }}</label><br>
{% endfor %}
<br><br>
<input type="submit" value="투표하기">
</form>
</body>
</html>
아직 URLConf, View만 설정했기에 Server polls page로 들어가면, Template(response가 none)이 없어 오류창이 뜸

하지만 MySQL에서 poll_choice를 조회해보면, votes의 숫자가 추가된 것을 알 수 있음

13. results라는 view 함수와 template을 이용해 누적된 투표수를 출력하고,
Redirect(HttpResponseRedirect과 reverse 모듈) 기능을 이용해서 polls page로 돌아가는 기능을 만들어야 함
urls.py(polls URLConf) 파일에서 views.results 함수에 대한 URLConf의 경로를 설정하고
from django.urls import path
from polls import views
app_name = 'polls'
urlpatterns = [
# http://127.0.0.1:80000/polls/
path('', views.index, name='index'),
# http://127.0.0.1:80000/polls/1~3/
path('<int:question_id>/', views.detail, name='detail'),
# http://127.0.0.1:80000/polls/1~3/vote/
path('<int:question_id>/vote/', views.vote, name='vote'),
# http://127.0.0.1:80000/polls/1~3/results/
path('<int:question_id>/results/', views.results, name='results'),
]
14. polls 폴더의 views.py에서 results 함수를 정의하고,
from django.shortcuts import render, get_object_or_404
from polls.models import Question
from django.http import HttpResponseRedirect # 장고에서 Redirect 모듈 불러오기
from django.urls import reverse # 장고에서 Reverse 모듈 불러오기
def index(request):
question_list = Question.objects.all().order_by("-pub_date")
context = {
"q_list": question_list
}
return render(request, "polls/index.html", context)
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
context = {
"my_question": question
}
return render(request, "polls/detail.html", context)
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
choice = question.choice_set.get(pk=request.POST['choice'])
choice.votes += 1
choice.save()
# redirect를 사용해서 client에게 응답을 주지만, 그 내용이 다른 URL에 request를 보내라는 것. args 안은 튜플!
return HttpResponseRedirect(reverse('polls:results', args=(question.id,)))
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
context = {
"my_question": question
}
return render(request, 'polls/results.html', context)
15. templates/polls 폴더 안에 results.html 생성한 뒤 내용을 입력함
앵커 <a href="">로 polls page의 URL을 직접 지정할 수 있지만 URL이 바뀔 가능성이 있으므로(유지보수 위해), urls.py(polls URLConf) 파일에서 지정한 namespace와 Template Tag를 사용해 연결하는 것이 좋음
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
현재 질문은 : {{ my_question.question_text }}
<br><br><br>
<ul>
{% for choice in my_question.choice_set.all %}
<li>{{ choice.choice_text }} - {{ choice.votes }} 표</li>
{% endfor %}
</ul>
<a href="/polls/">다시 투표하기</a> {#URL의 경로 직접 지정하기#}
<br><br>
<a href="{% url 'polls:index' %}">다시 투표하기</a> {#템플릿 태그 안에 namespace를 넣어 URL을 알아옮#}
</body>
</html>

이로써 투표 프로젝트 완성!
1. 1/17 월 | 2. 1/18 화 | 3. 1/19 수 | 4. 1/20 목 | 5. 1/21 금 |
취업 특강 | 파이썬 환경 설정 (파이참, 아나콘다, 주피터 노트북) |
파이썬 데이터 타입 (list, tuple) |
파이썬 데이터 타입 (range, string, dictionary, set, bool) |
파이썬 사용자 정의 함수, 객체지향, 사용자 정의 클래스 |
6. 1/24 월 | 7. 1/25 화 | 8. 1/26 수 | 9. 1/27 목 | 10. 1/28 금 |
파이썬 사용자 정의 클래스, 사용자 정의 모듈 |
DB(MySQL) DBMS, MySQL 환경 설정, DB/테이블 생성, DB 입력·활용, Index |
DB(MySQL) View, 백업과 복원, DB 모델링, 관계(PK, FK), DML(CRUD), 데이터 타입 |
DB(MySQL) DML(CRUD), WHERE 조건, 패턴 매칭, SubQuery, 정렬, 그룹핑, 집계 함수, 트랜잭션(ACID 특성) |
DB(MySQL) JOIN, UNION, NOT IN, WEB |
11. 2/3 목 | 12. 2/4 금 | 13. 2/7 월 | 14. 2/8 화 | 15. 2/9 수 |
WEB WebStorm 환경 설정, HTML, CSS, JavaScript, jQuery CDN |
WEB jQuery 문법, Selector, Method |
WEB jQuery Method, Event, AJAX |
GitHub 특강 소스코드 관리, Fork, Clone, Branch, Commit, Push, Pull-Request, Rebase |
GitHub 특강 프로젝트 관리, Fetch, Rebase, Merge, Conflict |
16. 2/10 목 | 17. 2/11 금 | 18. 2/14 월 | 19. 2/15 화 | 20. 2/16 수 |
WEB jQuery AJAX, Bootstrap, Open API |
Django WSGI, MVC, MVT, ORM |
Django MVT, ORM |
Django MVT, ORM, Redirect |
Django 게시판 |
* 프로젝트가 비슷하게 반복되므로, 과정과 코드를 익히자!