TIL | Django - 프로젝트 시작하기3

송치헌·2021년 8월 13일
1

TIL | Wecode - Django

목록 보기
3/18
post-thumbnail

이 프로젝트는 장고 공식 홈페이지에 올라온 첫 번째 장고 앱 작성하기, part 3 를 보고 작성한다.

무엇을 배웠는가

part2에 이어서 이제 view를 추가해보자.

# polls/views.py

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)

각 엔드포인트에서 어떤 결과를 출력할지 보여주는 문구를 작성하는 파일이다.

이제 path()를 호출하여 새로운 뷰를 polls.urls모듈에 연결하여 장고에게 알려준다.

# polls/urls.py

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

위에서 작성한 views파일을 urls파일에게 import하여 각각의 url을 연결시켜주었다.

localhost:8000/polls/34
localhost:8000/polls/34/results/
localhost:8000/polls/34/vote/
를 각각 주소창에 입력하면 글씨가 적혀있는 것을 볼 수 있을 것이다.(서버를 가동한 후 들어가야 한다.)

뷰 조작하기

# polls/views.py

from django.http import HttpResponse

from .models import Question


def index(request):
    latest_question_list = Question.objects.order_by('-pub_date')[:5]
    output = ', '.join([q.question_text for q in latest_question_list])
    return HttpResponse(output)

# Leave the rest of the views (detail, results, vote) unchanged

여기서 문제는 하드 코딩된 부분을 변경하기 위해서는 템플릿을 작성하여 python코드로부터 디자인을 분리해야 한다.

# 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 %}

이제 이렇게 만들어진 템플릿을 views파일에 올려보자.

# polls/views.py
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))

polls/index.html에 작성한 값을 views파일에서 context에 들어가게 된다.

render()

템플릿에 context를 넣어서 표현한 결과를 HttpResponse객체와 함께 돌려주는 구문은 자주 쓰인다. 그래서 장고에서는 이런 shortcuts(단축 기능)을 사용할 수 있게 해준다.

# polls/views.py

from django.shortcuts import render

from .models import Question


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

render를 import해주게 되면 더 이상 loader와 HttpResponse를 임포트하지 않아도 된다.

만약 detail, results, vote에서 stub 메소드를 가지고 있다면, HttpResponse를 적어주어야 한다.

404 Error

잘못된 접근을 하거나 인증받지 않은 사용자가 접근하면 접근을 하지 못하게 막아주어야 한다. 그래서 이런 비정상적인 접근에 대해서는 Error를 보여주어야 한다.


# polls/views.py

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

이렇게 try ~ except 구문으로 에러를 잡아주었다. 일단 이 코드를 동작시키기 위해서 detail.html이라는 파일을 작성해 주어야 한다. 동작하는지 먼저 보기위해 아무 내용이나 적어놓는다.

# polls/templates/polls/detail.html
{{ question }}

만약 객체가 존재하지 않으면 get_object_or_404 함수를 이용하여 404 에러를 일으킬 수 있다.

# polls/views.py

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

다시 템플릿 안에 있는 detail.html파일로 가서 임시로 작성한 글을 지우고 다음 코드를 작성한다.

# 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 이름 공간 정하기

polls/urls.py 파일에 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 템플릿의 기존 내용을 아래있는 것과 같이 바꾼다. 첫번째는 기존 방식이고 두번째가 바뀐 방식이다. 두번째 방법처럼 작성하면 된다.

# polls/templates/polls/index.html

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

어디에 적용했는가

part1, part2와 같이 튜토리얼을 진행하며 배운 내용 적용

어려웠던 점은 무엇인가

(없음)

profile
https://oraange.tistory.com/ 여기에도 많이 놀러와 주세요

0개의 댓글