장고 초급)절대 url 지정하기(URL dispatcher, URL namespaces)

하얀설표 | 작성시간 2024.06.30.

(2024.07.01. 수정됨.)

주요 파일 경로

blog
|- entry
|  |- urls.py
|  |- models.py
|- templates
   |- index.html

프로젝트에서 관리하는 app이 늘어날수록, app에서 사용하는 model이 많을수록 개별 url을 선언하고 관리하는 것은 매우 귀찮고, 번거로운 작업입니다.
이번에는 각 model에서 자신의 url을 스스로 밝힐 수 있도록 해줄 겁니다.

app_name 선언하기

다음과 같이 urls.py에 app_name을 선언하고, 글 목록과 개별 글 페이지 url에 name arg를 추가해줍니다.
글 목록은 index, 개별 글은 detail이라는 이름을 사용하겠습니다.

# entry/urls.py
from django.urls import path
from . import views
urlpatterns = [
    path('', views.index)
    path('post/', views.post),
    path('post/save/', views.save),
    path('<int:pk>/', views.detail),
    path('<int:pk>/edit/', views.edit, name='edit'),
    path('<int:pk>/save/', views.save, name='save'),
    path('<int:pk>/delete/', views.delete),
 ]

위 코드를 아래와 같이 수정합니다.

# entry/urls.py
from django.urls import path
from . import views
app_name = 'entry' # 추가
urlpatterns = [
    path('', views.index, name='index'), # 변경
    path('post/', views.post, name='post',), # 변경
    path('post/save/', views.save, name='save'), # 변경
    path('<int:pk>/', views.detail, name='detail'), # 변경
    path('<int:pk>/edit/', views.edit), # 변경
    path('<int:pk>/save/', views.save), # 변경
    path('<int:pk>/delete/', views.delete, name='delete'), # 변경
]

url namespace

장고는 url namespace라는 기능을 제공합니다.
url의 이름을 통해 url 경로를 찾기 위해 사용하는데, "{url name}" 또는 "{app name}:{url name}" 조합으로 사용되는 것이 일반적입니다.
앞서 추가한 url name들을 활용하자면 글 목록은 "entry:index", 개별 글은 "entry:detail"이라는 이름을 가집니다.
"{url name}"만 선언하는 경우에는 config/urls.py에서만 해당하는 url을 찾습니다.

get_absolute_url 선언하기

models.py를 열고 이전에 작성한 Post class에 get_abolute_url method를 추가합니다.
사실 method의 이름은 아무렇게나 해도 상관없는데, 장고 공식 문서에서 get_absolute_url이라는 이름으로 소개하고 있어서 그 명칭을 그대로 사용합니다.

# entry/models.py
from django.db import models
from django.shortcuts import resolve_url # 추가
class Post(models.Model):
    title = models.CharField(max_length=30,)
    content = models.TextField(max_length=999, default='',)
    date_post = models.DateTimeField(auto_now_add=True,)
    date_edit = models.DateTimeField(auto_now=True,)
    # 추가
    def get_absolute_url(self):
        return resolve_url('entry:detail', self.pk)

resolve_url

resolve_url은 urls.py를 탐색해 전달받은 args에 해당하는 url을 찾아주는 코드입니다.

템플릿 수정하기

이전에 작성한 index.html을 열어 "<a href="/entry/{{ object.pk }}">"라고 작성했던 부분을 "<a href="{{ object.get_absolute_url }}">"으로 변경해줍니다.

# index.html
<head></head>
<body>
    {% if request.user.is_anonymous %}
    <div>
        <a href="/admin/login/?next={{ request.get_full_path }}">로그인하기</a>
    </div>
    {% else %}
    <p>"{{ request.user.username }}"님</p>
    <form action="/admin/logout/?next={{ request.get_full_path }}" method="post">
        {% csrf_token %}
        <input type="submit" value="로그아웃">
    </form>
    {% endif %}
    <br>
    <h1>{{ title }}</h1>
    <a href="{% url 'entry:post' %}">글 작성하기</a>
    <article>
        {% for object in objects %}
        <p><a href="{{ object.get_absolute_url }}">{{ object.title }}</a></p>
        <p>get_absolute_url : {{ object.get_absolute_url }}</p>
        <p>url filter : {% url 'entry:detail' object.pk %}</p>
        {% empty %}
        <p>작성된 글이 없습니다.</p>
        {% endfor %}
    </article>
</body>

url filter

index.html을 다시 보면 "{{ object.get_absolute_url }}" 외에도 "{% url 'entry:post' %}"와 "{% url 'entry:detail' object.pk %}"라는 html 코드를 추가해놨습니다.
{% url ~ %}은 장고 템플릿에서 사용하는 템플릿 필터로, resolve_url과 같은 역할을 수행합니다.

{% url 'entry:post' %}은 다른 arg를 필요로 하지 않는 url이고,
{% url 'entry:detail' object.pk %}는 pk라는 arg를 필요로 하는 url이기 때문에 {% url {url name} {arg} %} 형식으로 작성되었습니다.

확인해보기

이제 url을 하나하나 찾을 필요없이, urls.py에서 대응하는 url을 장고 프로젝트가 알아서 찾아올 수 있게 되었습니다.

get abolute url 적용 확인



이 글의 댓글 기능은 일부러 막아놓았습니다. 궁금한 내용이 있다면 게시판을 이용해주세요!