파이썬-장고

Django (4)

threegopark 2021. 7. 11. 21:38
728x90

1. 애플리케이션 개발하기 - View & Template 코딩

 

polls 애플리케이션은 질문 리스트, 하나의 질문에 대한 선택지, 결과 페이지의 총 3개의 페이지를 가지고 있다. 즉, 이 3개의 페이지를 시각적으로 보여주기 위해 필요한 View와 Template를 코딩할 차례이다.

 

앞서 Model 코딩을 통해 테이블을 설계하였으니, 이번에는 클라이언트의 요청에서부터 응답까지의 처리 흐름에 대한 로직을 설계해야 한다. 다음과 같이 4개의 URL과 뷰가 필요하다고 판단하고 설계한다. (물론, 이게 정답은 아니다.)


  • View는 URL과 1:1 관계로 매핑된다. (N : 1 도 가능함) --> (URL / View 매핑 = URLConf) // urls.py에 작성한다.

 

1.1 URLconf 코딩 (뷰 <-> URL 매핑)

 

urls.py 파일에 코딩

from django.contrib import admin
from django.urls import path
from polls import views

#URL 패턴 매칭은 위에서 아래로 진행! 순서에 유의해야한다.
urlpatterns = [
    path('admin/', admin.site.urls),
    path('polls/', views.index, name='index'),
    path('polls/<int:question_id>/results/', views.results, name='results'),
    path('polls/<int:question_id>/vote/', views.vote, name='vote'),
]

+ path() 함수?

  • route : URL 패턴 표현하는 문자열 (=URL 스트링)
  • view : URL 스트링이 매칭되면 호출되는 뷰 함수. HttpRequest 객체 & URL 스트링에서 추출된 항목이 인자로 전달
  • kwargs : URL 스트링에서 추출된 항목 외에 추가적인 인자를 뷰 함수에 전달할 때, 파이썬 사전 타입으로 인자를 정의
  • name : 각 URL 패턴별로 이름을 붙여줌. (정의된 name은 보통 템플릿 파일에서 많이 사용됨)

예시 : path('polls/', views.index, name='index')

  1. 만일 URL이 /polls/이라면 path('polls/', views.index, name='index')가 매칭된다.
  2. 매칭 후 URL 스트링에서 따로 추출되는 항목이 없으므로 views.index가 호출된다. (이 URL 패턴의 이름을 index라 지정)

예시 : path('polls/<int:question_id>/', views.detail, name='detail')

  1. 만일 URL이 /polls/3/ 이면 위의 path 함수가 매칭되고, URL 스트링에서 3이 추출되므로 뷰 함수를 호출 시 views.detail (request, question_id=3) 처럼 인자가 대입된다.
  2. 이러한 URL 패턴의 이름을 detail이라고 지정한다.

그리고 이러한 urlconf 내용은 settings.py 파일에 ROOT_URLCONF 항목으로 정의되고, 장고는 URL 분석 시, 이 항목에 정의된 urls.py 파일을 가장 먼저 분석한다는 것을 알아두자.

 

뿐만 아니라 URLconf를 코딩할 때 앞에서처럼 하나의 urls.py 파일에 작성할 수도 있지만, 다음과 같이 mysite/urls.py 와 polls/urls.py 2개의 파일에 작성할 수도 있다. 물론 후자의 방법이 더 좋은 방법이다.

  • URLconf 모듈을 계층적으로 구성하게 되면 변경과 확장이 쉬워진다. 만일 URL의 polls를 vote로 변경한다면 전자의 경우 4개의 url 패턴을 모두 수정해야 하지만, 2개의 파일로 URLconf를 코딩한 경우는 상위 URLconf에서 1개의 패턴만 수정하면 된다. 이는 애플리케이션의 재사용면에서도 효율적이다.
#mysite.urls.py (2 개의 파일에 작성하는 경우)

from django.contrib import admin
from django.urls import path, include

urlpatterns = [
    path('admin/', admin.site.urls),
    path('polls/', include('polls.urls')),
]
#polls.urls.py

from django.urls import path
from . import views

app_name = 'polls'
urlpatterns = [
    path('', view.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'),
]
  • 여기서 app_name 변수는 URL 패턴의 이름이 충돌되는 것을 방지하는 것이다. 예를 들어, polls 앱과 blog 앱 두 개의 URL 패턴 이름이 모두 detail 인 경우, polls:detail   //   blog:detail    의 형식으로 구분할 수 있다.

 

1.2 뷰 함수 index() 및 템플릿 작성

 

  • 뷰 함수와 템플릿은 서로에게 영향을 미치기 때문에 보통 같이 작업을 한다. 
  • UI를 구현하기 위한 템플릿 파일은 ch3\polls\templates\polls 의 새로운 디렉토리를 만들어 위치시킨다. (mkdir templates  // mkdir templates/polls 명령어)
  • 개발하고자 하는 화면의 UI 템플릿 파일을 제작한다.

index.html 템플릿 코딩

{% if latest_question_list %}             ---------------   (1)

    <ul>                                  ---------------   (2)
    {% for question in latest_question_list %}
        <li><a href = "/polls/{{question.id}}/">{{question.question_text}}</a></li>
    {% endfor %}
    </ul>
    
{% else %}                                ----------------  (3)
    <p>No polls are available.</p>
{% endif %}

 

  1. latest_question_list 객체는 index() 뷰 함수에서 넘겨주는 파라미터
  2. latest_question_list 객체의 내용을 순회하면서 question_text를 순서 없는 리스트로 화면에 보여준다. (<ul>, <li> 태그 역할) 또한, 각 텍스트에 URL 링크를 연결한다. (<a href> 속성). URL 링크는 /polls/3/과 같은 형식임.
  3. 만약 latest_question_list 객체에 내용이 없다면 "No polls~" 문장을 화면에 보여줌

위의 템플릿을 작성하면서 index.html 템플릿에 필요한 변수가 무엇인지를 알아야 한다. 그 다음에는 템플릿에 필요한 변수를 전달할 수 있도록 index() 뷰 함수를 코딩하는 것이다. (이번 예제에서는 question_text와 question_id 두 가지 변수가 필요하다.)

 

index() 뷰 함수 코딩

from django.shortcuts import render
#장고의 단축 함수인 render

from polls.models import Question

#뷰 함수 정의. request는 뷰 함수의 필수 인자!
def index(request):
	#템플릿에 넘겨줄 객체의 이름은 latest_question_list
    #Question 테이블 객체에서 pub_date 컬럼의 역순으로 정렬하여 5개의 최근 Question 객체를 가져와서 만듬
    latest_question_list = Question.objects.all().order_by('-pub_date')[:5]
    
    #템플릿에 넘겨주는 방식은 파이썬 사전 타입
    #템플릿에 사용될 '변수 명'과 '객체'를 매핑하는 사전으로 context 변수를 제작, render()에 보내줌
    context = {'latest_question_list': latest_question_list}
    
    return render(request, 'polls/index.html', context)
  • render() 함수는 템플릿 파일인 polls/index.html에 context 변수를 적용하여 사용자에게 보여줄 최정 HTML 텍스트를 만들고, 이를 담아서 HttpResponse 객체를 반환함(최종적으로 클라이언트에게 응답할 데이터)

 

'파이썬-장고' 카테고리의 다른 글

Django (3)  (0) 2021.07.07
Django (2)  (0) 2021.07.07
Django (1)  (0) 2021.07.07
파이썬 웹 표준 라이브러리  (0) 2021.07.03
웹 프로그래밍의 이해  (0) 2021.06.21