일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- Spark
- Optimization
- ELK
- AWS
- 스파크
- python
- 키바나
- Algorithm
- CentOS
- elasticsearch
- RecommendationSystem
- Django
- leetcode
- 파이썬
- dfs
- programmers
- dump
- 장고
- 리트코드
- Medium
- solution
- twosum
- 깊이우선탐색
- 엘라스틱서치
- kibana
- 알고리즘
- daspecialty
- 프로그래머스
- 해시
- Easy
- Today
- Total
Archive
[Django] View / Template Coding Overview (실습2) 본문
0. Overview
- View/ Template 코딩전에 Request / Response에 대한 로직을 설계하고 시작해야 한다.
- URL ~ View 는 N:1 매핑이 가능하다.
코딩순서
urls.py
views.index()
views.detail()
views.vote()
views.results()
1. URLconf
위의 로직에 따라 URLconf와 View를 설계해 보면 아래와 같다
URL 패턴 | 뷰 이름 | 뷰가 처리하는 내용 |
/polls/ | index() | index.html template 보여줌 |
/polls/5/ | detail() | detail.html template 보여줌 |
/polls/5/vote/ | vote() | detail.html에 있는 form을 POST방식으로 처리 |
/polls/5/results/ | results() | results.html template 보여줌 |
urls.py에는 Urlpatterns 내 path()함수를 통해 URL~ View 매핑을 정의한다.
1) poll/urls.py
from django.urls import path
from . import views
app_name='polls'
urlpatterns = [
path('', views.index, name = 'index'),
path('<int:question_id>/', views.detail, name = 'detail'),
path('<int:question_id>/results/', views.results, name = 'results'),
path('<int:question_id>/vote/', views.vote, name = 'vote'),
]
2) project/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('polls/', include('polls.urls')),
]
*path() 함수는 route, view(이상 필수), kwargs, name (이상 선택) parameter를 받는다
*path내 name인자가 애플리케이션에 따라 중복될 수 있으므로 app name을 :을 통해 명시해주는 것이 일반적이다.
2. view.index()
사람에 따라 templaate , view 구현 순서는 다르나, 일반적으로는 만들려는 화면을 먼저 그려놓고 로직을 구현을 하는 것 같다.
① 간단한 화면 UI 설계 (index.html)
② index.html 구현 (Template)
- index.html을 작성하면서 어떤 context 변수를 template에 넘겨줘야 할 지 파악한다.
: 아래의 예시 코드에선 question_text, question.id가 필요하므로, 이 두 가지 정보가 같이 들어있는 Question 객체를 view함수로 부터 받으면 된다. - index.html 이 저장되는 위치는 나중에 애플리케이션이 많아졌을 시의 관리의 편의성을 위해 Root Dir/Application Dir/Template Dir/Application Name/index.html 이다. (ex.mysite/polls/template/polls/index.html)
{% if latest_question_list %}
<ul>
{% for question in latest_question_list %}
<li>
<a href="/polls/{{ question.id }}/'">{{ question.question_text }}</a>
</li>
{% endfor %}
</ul>
{% else %}
<p>No polls are available</p>
{% endif %}
③ views.py 내 index() 구현
from django.shortcuts import render
from polls.models import Question
def index(request):
latest_question_list = Question.objects.all().order_by('-pub_date')[:5]
context = {'latest_question_list' : latest_question_list}
return render(request, 'polls/index.html', context)
*render() : Template 변수는 Dict()형태로 전달하는데, 이를 Render함수에 보내면, 이를 기반으로 HTML text를 만들고, Http Response 객체를 반환한다.
3. view.detail()
① 간단한 화면 UI 설계 (detail.html)
② detail.html 구현 (Template)
- detail.html을 작성하면서 어떤 context 변수를 template에 넘겨줘야 할 지 파악한다.
: 아래의 예시 코드에선 question_text, question.id,. question.choice_set 변수가 필요하므로, 같이 들어있는 Question 객체를 view함수로 부터 받으면 된다. - detail.html 이 저장되는 위치는 나중에 애플리케이션이 많아졌을 시의 관리의 편의성을 위해 Root Dir/Application Dir/Template Dir/Application Name/detail.html 이다. (ex.mysite/polls/template/polls/detail.html)
<h1>{{ question.question_text }}</h1>
{% if error_message %}<p><strong>{{ error_message }}</strong></p>{ % endif%}
<form action ="{% url 'polls:vote' question.id %}" method="post">
{% csrf_token %}
{% for choice in question.choice_set.all %}
<input type="radio" name="choice" id="choice{{ forloop.counter }}" value ="{{ choice.id }}" />
<label for="choice{{ forloop.counter }}"> {{ choice.choice_text }}</label><br />
{% endfor %}
<input type="submit" value="Vote" />
</form>
* 서버측의 데이터를 변경하는 경우 POST 방식 사용
* 보안 측면에서 CSRF(Cross Site Request Forgery) 공격을 막기 위해 {% csrf_token%} template 태그 사용
* radio button : 옵션 선택할 때 사용하는 ○ 모양 버튼. 해당 버튼을 선택하면 POST 데이터가 choice=3 을 choice.id 형태로 구성하게끔 되어있다.
*forloop.counter : for loop 실행 횟수를 담고있는 template 변수
*vote버튼을 클릭하면 사용자가 선택한 form 데이터가 POST방식으로 polls:vote URL로 전송된다. <input>태그의 name, value 속성 값들이 request.POST 사전에 key, value로 사용된다
③ views.py 내 detail() 구현
index.html에서 질문 하나를 클릭하면, /polls/1/과 같은 URL이 넘어오고, detail() view 함수가 호출된다.
from django.shortcuts import render, get_object_or_404
from polls.models import Question
def detail(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/detail.html', {'question': question})
*get_object_or_404 : Question 클래스로부터 pk=-question_id 검색 조건에 맞는 객체 조회, 조건에 맞는 객체가 없으면 Http404 Exception 발생
4. view.vote() 및 redirection
detail.html에서 template에 있는 form 을 제출하면, /polls/5/vole/와 같은 URL 이 POST 방식으로 넘어온다.
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse
from polls.models import Choice, Question
# Create your views here.
def vote(request, question_id):
question = get_object_or_404(Question, pk=question_id)
try:
selected_choice = question.choice_set.get(pk=request.POST['choice'])
except (KeyError, Choice.DoesNotExist):
return render(request, 'polls/detail.html', {
'question' : question,
'error_message' : "You didn't select a choice.",
})
else:
selected_choice.vote+=1
selected_choice.save()
return HttpResponseRedirect(reverse('polls:results',args=(question.id,)))
* Form 의 POST 데이터에서 'choice'라는 key가 없으면 KeyError Exception 발생 / 검색 조건에 맞지 않으면 DoesNotExist Exception 발생
- Exception이 발생하면 render() 함수에 의해, question과 error_message Context 변수를 detail.html로 전 / 사용자에게는 Error message와 함께 Form을 다시 보여줘서 데이터를 재입력 할 수 있도록 함
*vote() 가 반환하는 객체는 HttpResponseRedirect로, 객체의 생성자가 Redirect할 Target URL을 인자로 받는다. (Target URL은 reverse()로 생성)
*reverse() : URL 패턴 이름, URL String에 사용될 Parameter를 받아, URL 패턴 이름으로 부터 URL String을 만듦
5. view.results()
① views.py 내 results() 구현
results() view 함수의 호출과 연계된 URL은 votes() view 함수의 Redirect 결과로 받는다
: 즉, Form 을 처리한 후 결과를 보여주는 페이지로 redirect시켜주기 위해 votes()에서 redirect 객체를 return 한다. 웹에서는 이를 받아서 redirect URL로 다시 요청을 보내게 된다
from django.shortcuts import render, get_object_or_404
from django.http import HttpResponseRedirect, HttpResponse
from django.urls import reverse
from polls.models import Choice, Question
# Create your views here.
return HttpResponseRedirect(reverse('polls:results',args=(question.id,)))
def results(request, question_id):
question = get_object_or_404(Question, pk=question_id)
return render(request, 'polls/results.html', {'question':question})
② 간단한 화면 UI 설계 (results.html)
③ results.html 구현 (Template)
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
<li>{{ choice.choice_text }} - {{ choice.votes }} vote{{ choice.votes|pluralize }}</li>
{% endfor %}
</ul>
<a href = "{% url 'pools:detail' question.id %}">Vote again?</a>
*pluralize : | 앞의 choice.votes 값에 따라 복수 접미사(s)를 붙여주는 함수
*{ % url % } : View 내의 reverse()와 같이, URL 스트링을 추출할 수 있게 해주는 태그
6. run server
① admin page 에서 데이터 등록
Question 등록
Choice 등록
② /polls 확인
*후기
너무 허접해서 웃기고 조금은 황당하다. 원래 처음은 다 이렇게 시작하는 것이라며,,
파이썬 웹 프로그래밍 - 3. Django 웹프레임워크
'------ Web ------ > Backend' 카테고리의 다른 글
[Django] Form (0) | 2022.07.03 |
---|---|
[Django] Template System (0) | 2022.06.28 |
[Django] Admin (0) | 2022.06.26 |
[Django] Model Coding Overview (실습1) (0) | 2022.06.23 |
[Django] 장고 기본개념 ( MVT / Structure / Project생성 / Application생성 ) (0) | 2022.06.19 |