ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Django tutorial] django official tutorial part3 정리
    Software, Computer Science/Django, Flask 2020. 2. 3. 21:29

    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/

    댓글

Designed by Tistory.