먼저 question_list.html 템플릿에 사용된 다음 링크를 보면
<li><a href="/pybo/{{ question.id }}/">{{ question.subject }}</a></li>
질문 상세를 위한 URL 링크이다. URL 링크의 구조가 자주 변경된다면 템플릿에서 사용한 모든 URL들을 일일이 찾아가며 수정해야 하는 리스크가 발생한다. 링크의 주소가 하드코딩되어 있기 때문이다.
실제 링크 대신 링크의 주소가 1:1 매핑되어 있는 별칭을 사용해야 한다. {% url %} 템플릿 태그를 사용하면 이러한 문제를 해결할 수 있다.
1. URL 별칭 지정하기
// pybo\\urls.py
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
]
링크의 주소 대신 별칭을 사용하려면 URL 매핑에 name 속성을 부여하면 된다.
- http://localhost:8000/pybo/ URL은 index,
- http://localhost:8000/pybo/2와 같은 URL에는 detail 이라는 별칭을 부여한다.
2. 템플릿에서 URL 별칭 사용하기
// pybo\\question_list.html
{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="{% url 'detail' question.id %}">{{ question.subject }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>질문이 없습니다.</p>
{% endif %}
하드코딩 되어 있던 /pybo/{{ question.id }} 링크를 {% url 'detail' question.id %}로 변경했다. 여기서 question.id는 URL 매핑에 정의된 <int:question_id>에 전달해야 하는 값을 의미한다.
파라미터명 전달 한 개의 파라미터를 전달할 경우에는 다음과 같이 사용했다.
{% url 'detail' question.id %}
2개 이상의 파라미터를 사용해야 한다면 다음과 같이 공백 문자 이후에 덧붙여주면 된다.
3. URL 네임스페이스
pybo 앱 이외의 다른 앱이 프로젝트에 추가 될 수도 있다. 이런 경우 서로 다른 앱에서 동일한 URL 별칭을 사용하면 중복이 발생한다. 이 문제를 해결하려면 pybo/urls.py 파일에 네임스페이스를 의미하는 app_name 변수를 지정해야 한다.
// pybo/urls.py
from django.urlsimport path
from .import views
app_name = 'pybo'
urlpatterns = [
path('', views.index, name='index'),
path('<int:question_id>/', views.detail, name='detail'),
]
app_name을 pybo로 설정하였다. 그런데 이렇게 수정하고 http://localhost:8000/pybo/ 페이지를 요청하면 다음과 같은 오류가 발생한다.
이 오류는 네임스페이스를 추가했기 때문에 발생한 오류이다. 이 오류를 해결하려면 템플릿에서 사용한 URL 별칭에 네임스페이스를 다음과 같이 지정해야 한다.
[파일명: C:\\projects\\mysite\\templates\\pybo\\question_list.html]
// pybo\\question_list.html
{% if question_list %}
<ul>
{% for question in question_list %}
<li><a href="{% url 'pybo:detail' question.id %}">{{ question.subject }}</a></li>
{% endfor %}
</ul>
{% else %}
<p>질문이 없습니다.</p>
{% endif %}
detail 앞에 pybo 라는 네임스페이스를 붙여준 것이다.