Django Official Tutorial part3 정리

ybear90·2020년 2월 10일
0

Django

목록 보기
3/12

Part 3

django에서의 view는 특정 기능과 알고리즘을 수행하며 template을 제공해 주는 역할을 하는 웹페이지이자 모듈이다. polls 앱 기준으로 다음과 같은 4개의 view를 구성해 볼 수 있다.(실제 MVC 디자인 패턴에서 Controller에 해당한다, 또한 View는 django에서 template이나 FE단의 페이지가 될 수 있다)

  • 질문 "index" page : 질문 표시
  • 질문 "detail" page : 질문 및 투표 서식 표시
  • 질문 "results" page : 특정 질문에 대한 결과 표시
  • 투표 기능 : 질문에 대해 투표할 수 있는 기능
from django.shortcuts import HttpResponse

def index(request):
    return HttpResponse("Hello, world. You're at the polls index.")

def detail(request, question_id):
    return HttpResponse("You're looking at question %s." % question_id)

def results(request, question_id):
    response = "You're looking at the results of question %s."
    return HttpResponse(response % question_id)

def vote(request, question_id):
    return HttpResponse("You're voting on question %s." % question_id)

URL 패턴 또한 URLConf를 통해 간결하게 만들 수 있으며 해당 패턴을 view에 연결 시켜 주기도 한다.(URL dispatcher 참고)

from django.urls import path

from . import views

urlpatterns = [
    # ex: /polls/
    path('', views.index, name='index'),
    # ex: /polls/5/
    path('<int:question_id>/', views.detail, name='detail'),
    # ex: /polls/5/results/
    path('<int:question_id>/results/', views.results, name='results'),
    # ex: /polls/5/vote/
    path('<int:question_id>/vote/', views.vote, name='vote'),
]

urlpatterns 리스트 안 두번째 path 메소드를 간단히 설명하면 views.py 안에 있는 detail() 을 통하여 URL에 입력한 ID를 출력하게 되어 있고 해당 url을 통하여 투표 서식을 볼 수 있다. 결과적으로 detail() 엔 다음과 같이 값이 전달된다

detail(request=<HttpRequest object>, question_id=34)

view가 기능 할 수 있게끔 구성해보기

view가 어떤 식으로 동작하는지 템플릿의 연결관계와 더불어 튜토리얼에서 설명하고 있다. 이 파트에선 그 과정을 요약해서 한번에 정리한다.

먼저 polls와 관련한 index.html 페이지를 다음과 같이 만들어준다

<!-- polls/templates/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 %}

원래는 아래와 같이 template을 직접 load 해서 HttpResponse 객체를 리턴하게끔 되어 있지만 django에선 이걸 축약해서 render 메소드를 통해 구현하게 끔 되어 있다.

from django.http import HttpResponse
from django.template import loader

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    template = loader.get_template('polls/index.html')
    context = {
        'latest_question_list': latest_question_list,
    }
    return HttpResponse(template.render(context, request))

404에러를 일으킬 때의 예외처리 또한 아래와 같은 예로 구성이 되어 있는데

from django.http import Http404
from django.shortcuts import render

from .models import Question
# ...
def detail(request, question_id):
    try:
        question = Question.objects.get(pk=question_id)
    except Question.DoesNotExist:
        raise Http404("Question does not exist")
    return render(request, 'polls/detail.html', {'question': question})

이 또한 shortcuts 모듈 안에 있는 get_object_or_404 메소드를 통해 간단히 구현할 수 있다.

from django.shortcuts import get_object_or_404, render

from .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})

요약하면 views.py에서 복잡한 처리 과정이 있는데 shortcuts 모듈 안에 있는 메소드들이 간단히 구현하게 해준다는 것이다.

템플릿 문법 또한 기존에 html/css와는 다른 모습에 이질적이지만 어느정도 잘 활용할 줄 안다면 url경로의 의존성을 줄이거나 반복문이나 조건문의 사용을 통해 긴 코드도 짧게 줄일 수 있는 장점이 있다.

<!-- polls/templates/polls/detail.html -->
<h1>{{ question.question_text }}</h1>
<ul>
{% for choice in question.choice_set.all %}
    <li>{{ choice.choice_text }}</li>
{% endfor %}
</ul>

템플릿 문법을 이용하여 하드코딩된 url 제거하는 방법 예제

{% if latest_question_list %}
    <ul>
    {% for question in latest_question_list %}
        <!-- <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li> -->
        <li><a href="{% url 'detail' question.id %}">{{ question.question_text }}</a></li>
    {% endfor %}
    </ul>
{% else %}
    <p>No polls are available.</p>
{% endif %}

URL의 이름공간(namespace) 정하는 방법

실제 django 프로젝트는 앱이 몇개라도 추가가 될 수 있다. 그렇다면 그 많은 app들 중에 URL을 어떻게 구분할까 ? 다시 말해 polls라는 앱에 detail이 있을 수도 있고 같은 프로젝트 내에 blog라는 앱에도 detail이라는 view가 있을 수도 있다. 이를 구분하기 위해 URLConf에 namespace를 추가한다.

# polls/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'),
]

이에따라 polls/index.html의 템플릿의 기존 내용을 아래와 같이 수정한다(어디에서 온 view인지 명시)

<li><a href="{% url 'polls:detail' question.id %}">{{ question.question_text }}</a></li>

Reference

https://docs.djangoproject.com/ko/3.0/intro/tutorial03/

하지만 요즘 개발 트렌드에서 template을 합쳐 full-stack으로 구현하는 추세가 아니기에 template 부분은 거의 만들지 않고 FE 개발로 그 역할이 넘어가 있는 편이다. 따라서 템플릿은 일단 참고로 알아 두고 정 필요하다 싶으면 찾아가며 쓰는 정도로 정리해두는게 맞을 듯 싶다.

profile
wanna be good developer

0개의 댓글