URL Reverse를 통해서 유연하게 URL 생성하기

2022. 1. 11. 19:18강의 정리/Django Views

반응형

출처 : https://www.inflearn.com/course/%ED%8C%8C%EC%9D%B4%EC%8D%AC-%EC%9E%A5%EA%B3%A0-%EC%9B%B9%EC%84%9C%EB%B9%84%EC%8A%A4/dashboard

 

장고(Django)를 배우기 시작한 입문자이시거나, 또는 배우고 싶은 생각이 있으신 분은 위 출처의 강의를 적극 추천드립니다!!!

 

 


 

 

URL Dispatcher

  • urls.py 변경만으로 "각 뷰에 대한 URL"이 변경되는 유연한 URL 시스템

 

HTTP 요청이 들어올 때, 즉 예를 들어서 검색을 하거나, 주소창에 직접 주소를 입력하거나, 어떠한 이벤트가 발생하여 백엔드(Django)에게 HTTP request가 들어올 때, 적합한 로직(View 함수)을 가진 URL로 매칭을 해주는 것이 URL Dispatcher이다.

https://devdongbaek.tistory.com/67

 

동백 // Django URL Dispatcher와 정규 표현식

URL Dispatcher " 특정 URL 패턴 -> View"의 List 프로젝트 / settings.py에서 최상위 URLConf 모듈을 지정 ROOT_URLCONF = 'dongbaek.urls' # 최초의 urlpatterns로부터 include를 통해, TREE 구조로 확장 urlpat..

devdongbaek.tistory.com

 

 


URL Reverse

  • python 코드 안에서 URL 템플릿 태그와 비슷하게 동작하는 기능이다.
  • urls.py에서 설정한 URL의 name이나, viewname을 통해서 다시 URL로 되돌릴 수 있다.

 


 

URL Reverse의 혜택

  • 개발자가 일일이 URL을 계산하지 않아도 되며, URL이 변경되더라도 누락 되지않고 URL Reverse가 변경된 URL을 추적
  • 즉 무슨 말이냐면
    •  https://wayhome25.github.io/django/2017/05/05/django-url-reverse/
    • "blog/" 주소로 서비스하다가 urlpatterns = [ path('blog/', views.post_list, name='post_list'), ] 아래와 같이 변경하면 자동으로 "weblog/" 주소로 서비스하게 됨 urlpatterns = [ path('weblog/', views.post_list, name='post_list'), ]
  •  
 

URL Reverse, 아는 사람은 꼭 쓴다는 get_absolute_url() · 초보몽키의 개발공부로그

특정 모델에 대한 Detail뷰를 작성할 경우, Detail뷰에 대한 URLConf설정을 하자마자, 필히 get_absolute_url설정을 해주세요. 코드가 보다 간결해집니다

wayhome25.github.io

 

 

만약 직접 URL을 계산한다면??

  1. blog앱 Post 목록을 보려면, post_list 뷰를 호출해야 하니
  2. urls.py를 뒤적거리며, URL을 일일이 계산해야한다.
  3. 계산이 마치면 그 때 /blog/ 주소를 사용할 수 있다.
  • 그런데 만약 url을 변경하고 싶다면??? 일일이 다 바꿔야 하는 불상사가 일어난다.

 

그러나 Django를 이용하면?

  1. blog앱 Post 목록을 보려면, post_list 뷰를 호출해야 함 # 끝!!!!
  2. urls.py를 뒤적거리며, URL을 일일이 계산해야한다.
  3. 계산이 마치면 그 때 /blog/ 주소를 사용할 수 있다.

 

 


 

URL Reverse를 수행하는 4가지 함수 

  • url 템플릿 태그
    • {% url="blog:post_detail" 100 %} # 문자열 URL
      {% url="blog:post_detail" pk=100 %} # 문자열 URL
       
    • 내부적으로 reverse 함수를 사용
  • reverse 함수
    • reverse('blog:post_detail', args=[100]) # 문자열 URL
      reverse('blog:post_detail', kwargs={'pk': 100}) # 문자열 URL​
       
    • 매칭 URL이 없으면 NoReverseMatch 예외 발생
  • resolve_url 함수 #reverse 함수를 조금 더 사용하기 쉽게
    • resolve_url('blog:post_detail', 100) # 문자열 URL
      resolve_url('blog:post_detail', pk= 100) # 문자열 URL
      resolve_url('/blog/100/') # 문자열 URL​
       
    • 매핑 URL이 없으면 "인자 문자열"을 그대로 리턴
    • 내부적으로 reverse  함수를 사용
  • redirect 함수 #resolve_url 함수 기능을 보충
    • redirect('blog:post_detail', 100) # HttpResponse 응답 (301 or 302)
      redirect('blog:post_detail', pk= 100) # HttpResponse 응답 (301 or 302)
      redirect('/blog/100/') # HttpResponse 응답 (301 or 302)​
       
    • 매칭 URL이 없으면 "인자 문자열"을 그대로 URL로 사용
    • 내부적으로 resolve_url 함수를 사용
    • view 함수 내에서 특정 url로 이동 하고자 할 때 사용 (Http Response)

 

 


URL Reverse 직접 사용해보기

 

urls.py의 urlpatterns에 name 속성이 지정되어있어야 한다.

urlpatterns = [ 
    path('', views.post_list, name='post_list'),
    path('<int:pk>/', views.post_detail, name='post_detail'),
    ]

 

Shell에서

>>> from django.urls import reverse
>>> from django.shortcuts import resolve_url

>>> reverse('instagram:post_list') 
'/instagram/'

>>> reverse('instagram:post_detail', args=[123]) 
'/instagram/123/'

>>> resolve_url('instagram:post_detail', 100)        
'/instagram/100/'

>>> resolve_url('instagram:post_detail', pk=100)        
'/instagram/100/'

 

 


 

모델 객체에 대한 detail 주소 계산

#모든 모델에 대해서 detail 페이지는 거의 존재한다 ex) 쇼핑몰의 item과 Item_detail, SNS의 Post와 Post_detail등 그러므로 detail 페이지의 URL을 알기 위해서는 위에서 알게 된 방법 말고도 더 간단한 방법도 존재한다.
resolve_url('instagram:post_detail', pk=post.pk) 

redirect('instagram:post_detail', pk=post.pk) 

{% url 'blog:post_detail' post.pk %}

 

위의 코드와 아래 코드는 같은 의미의 detail 주소 계산이다.

 

resolve_url(post)

redirect(post)

{{ post.get_absolute_url }}

# 아래 코드를 사용하기 위해서는 모델 클래스에 get_absolute_url()을 구현해야한다.

 

 

 


 

 

모델 클래스에 get_absolute_url()

  • 모델 클래스에 get_absolute_url()을 구현했다면, resolve_url과 redirect에서는 get_absolute_url()을 사용할 준비가 되어있기에, 바로 사용이 가능하다.
  • 템플릿에서는 모델에 구현한 get_absoulte_url()을 직접 호출하여 사용한다.
  • resolve_url 함수는 가장 먼저 get_absolute_url() 함수의 존재 여부를 체크하고, 존재할 경우 reverse를 수행하지 않고 그 리턴값을 즉시 리턴

 

특정 모델에 대한 Detail뷰를 작성할 경우, 코드가 보다 간결해지기 때문에 Detail뷰에 대한 URLConf설정을 
필히 get_absolute_url설정을 해야한다. 

 

 

 

  • 모델을 구현하였다면, get_absolute_url() 함수부터 구현하는 것이 좋다.

 

 

get_absolute_url() 작성

instagram/models.py

class Post(models.Model):
    --- 중략 --- 

    def get_absolute_url(self):
        return reverse('instagram:post_detail', args=[self.pk])

 

 

get_absolute_url() 활용

1. 템플릿의 tag로 활용

instagram/templates/instagram/post_list.html

<body>

            --- 중략 ---
                    <td>
                        <a href= "{{ post.get_absolute_url }}" >
                        {{ post.message }}       
             --- 중략 ---
    </table>

 

2. resolve_url, redirect를 통한 활용

from django.shortcuts import resolve_url
from django.shortcuts import redirect

resolve_url('blog:post_detail', post.id) # '/blog/105/'
resolve_url(post) # '/blog/105/' 인자의 인스턴스 메소드로 get_absolute_url 있는지 체크해서 리턴

print(redirect('blog:post_detail', post.id))
print(redirect(post))
# <HttpResponseRedirect status_code=302, "text/html; charset=utf-8", url="/blog/105/">

출처 : https://wayhome25.github.io/django/2017/05/05/django-url-reverse/

 

 


 

그 외 활용

 

CreateView / UpdateView

  • success_url(성공했을 때 이동할 주소)을 제공하지 않을 경우, 해당 model instance의 get_absolute_url 주소(즉 detail view)로 이동이 가능한지 체크하고, 이동이 가능할 경우 이동
  • 생성 / 수정하고나서 Detail 화면으로 이동하는 것이 자연스러운 시나리오 # 즉 네이버 블로그에서 글을 생성 / 수정하면 목록이 아닌 해당 글 화면으로 이동하는 것이 자연스러움
반응형