파이썬/장고 웹서비스 개발 완벽 가이드 with 리액트 강의를 듣고 정리한 글입니다.
장고는 urls.py를 통해 각 뷰에대한 URL이 변경되는 유연한 URL 시스템을 갖는다.
뷰에 대한 이름은 path에 name 파라미터를 지정하면 된다.
app_name은 앱 내의 네임스페이스 역할을 한다. post_list가 다른 앱에 존재하더라도 app_name을 통해 구분할 수 있다.
URL Reverse를 수행함으로써 개발자가 URL을 계산할 필요가 없다. 추후에 path의 url이 변경되더라도 유연한 대응이 가능하다.
# project/urls.py
urlpatterns = [
# ...
path('instagram/', include('instagram.urls')),
]
# instagram/urls.py
app_name = 'instagram' # app_name 설정. 네임스페이스 역할
urlpatterns = [
path('', views.post_list, name='post_list'), # name 파라미터 입력. 뷰의 이름.
path('<int:pk>/', views.post_detail, name='post_detail'),
]
instagram앱의 urls.py에서 정의한 url을 활용하는 예시이다.
템플릿 예시 및 reverse, resolve_url, redirect 등의 함수를 이용해서 서버코드에서도 활용이 가능하다.
url 내용을 변경하더라도 아래 예시들과 같이 URL Reverse를 사용한 코드는 변경할 필요가 없게된다.
instagram앱에서 post_list에 대한 URL을 가져온다 (instagram/
)
<!-- <a href="instagram/">포스트 리스트</a> (이런 하드코딩은 나중에 URL을 변경 시 함께 변경되어야 한다.) -->
<a href="{% url 'instagram:post_list' %}">포스트 리스트</a>
instagram앱에서 post_detail에 대한 pk=100일 때의 URL을 가져온다. (instagram/100
)
파라미터 이름(pk)는 생략이 가능하다.
<!-- <a href="instagram/100">100번 포스트</a> (마찬가지로 나중에 URL을 변경 시 함께 변경되어야 한다.) -->
<a href="{% url 'instagram:post_detail' 100 %}">포스트 리스트</a>
<a href="{% url 'instagram:post_detail' pk=100 %}">포스트 리스트</a>
reverse
: URL 문자열을 반환. args 또는 kwargs라는 파라미터 이름을 지정해서 정해진 타입으로 입력해야 한다. (args: 리스트 - 여러개일 경우 파라미터 순서대로 지정, kwargs: 사전 - 파라미터 이름 지정)
resolve_url
: URL 문자열을 반환. reverse를 래핑해서 편리하게 사용할 수 있도록 만든 함수. 동적으로 여러개의 파라미터를 입력하거나 파라미터 이름을 지정해서 입력한다.
redirect
: HttpResponse(301 or 302)를 반환한다. 뷰에서 특정 로직에 대한 리다이렉트 응답이 필요할 경우 사용가능. 내부적으로 resolve_url을 활용한다.
from django.urls import reverse
from django.shortcuts import resolve_url, redirect
reverse('instagram:post_detail', args=[100]) # '/instagram/100/' 반환
reverse('instagram:post_detail', kwargs={'pk': 100}) # '/instagram/100/' 반환
resolve_url('instagram:post_detail', 100) # '/instagram/100/' 반환
resolve_url('instagram:post_detail', pk=100) # '/instagram/100/' 반환
resolve_url('/instagram/100/') # '/instagram/100/' 반환
redirect('instagram:post_detail', 100) # /instagram/100/에 대한 HttpResponse 반환
redirect('instagram:post_detail', pk=100) # /instagram/100/에 대한 HttpResponse 반환
redirect('/instagram/100/') # /instagram/100/에 대한 HttpResponse 반환
다음 코드를
resolve_url('instagram:post_detail', pk=post.pk)
redirect('instagram:post_detail', pk=post.pk)
{% url 'instagram:post_detail' post.pk %}
다음과 같이 사용할 수 있다.
resolve_url(post)
redirect(post)
{{ post.get_absolute_url }}
get_absolute_url()
구현모델 클래스에 get_absolute_url 메서드를 구현하면 된다.
resolve_url 함수는 가장 먼저 get_absolute_url()함수의 존재 여부를 확인하고 존재한다면 reverse를 수행하지 않고 그 리턴값을 즉시 리턴하게 되어 있다.
redirect 또한 내부적으로는 resolve_url을 사용하기에 get_absolute_url() 구현 여부에 따라 영향을 받는다.
class Post(models.Model):
# ...
def get_absolute_url(self):
return reverse('instagram:post_detail', args=[self.pk])
get_absolute_url()
주소로 이동 가능한지 여부를 체크하고, 이동이 가능할 경우 이동한다.get_absolute_url()
을 구현할 것을 추천한다. 코드가 간결해 진다.