본문 바로가기

멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차/WEB

2/15 화

728x90

화요일!

 

PyCharm으로 지난번에 했던 Project(MyFirstWeb_0215) 생성, Django 설치 및 MySQL 연동을 똑같이 진행했다.

1. 오늘은 templates 폴더 안에 추가로 polls 폴더를 만들고 index.html 파일을 생성해줌

templates/polls 폴더 안에 index.html 만들고 내용 입력

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

HttpResponse 안에 질문에 대한 link 속성 지정하기

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

polls 폴더 안의 urls.py에 경로, URLConf 지정

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

polls 폴더의 views.py에서 detail 함수 정의

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

templates/polls 폴더 안에 detail.html 만들고 내용 입력

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

Server polls page에 질문 내용이 표현됨

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)이 없어 오류창이 뜸

Server polls vote page

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

MySQL polls_choice

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>

 

Server Results Page

이로써 투표 프로젝트 완성!

 

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
게시판

* 프로젝트가 비슷하게 반복되므로, 과정과 코드를 익히자!

728x90

'멀티캠퍼스 프로젝트형 AI 서비스 개발 5회차 > WEB' 카테고리의 다른 글

2/17 목  (0) 2022.02.17
2/16 수  (0) 2022.02.16
2/14 월  (0) 2022.02.14
2/11 금  (0) 2022.02.11
2/10 목  (0) 2022.02.10