Python/Django

URL 설계

yunajoe 2022. 10. 7. 08:21

# url 설계 
django는 view와 URL의 느슨한 결합이라는 철학을 가지고 있다 
그래서 view 구현이 직접 URL을 mapping하지 않고, URL mapping을 view 구현과 
따로 처리하여 URL을 보다 유연하게 정의한다 

// 스프링 vs // django 

=========================== 


django앱은 앱의 재사용성에 그 목적이 있다. 하나의 django앱을 이 프로젝트에서 
사용할 수 있다
그런데, 같은 django앱이더라도 프로젝트/서비스에서 요구되어지는 URL/prefix 가 
다를 수 있다. django는 유연하게 다르게 지정할 수 있는 방법을 제공 


# blog/urls.py
urlpatterns = [
 path(""
, views.post_list),
 path("<int:pk>/", views.post_detail),
]
# blog/views.py
def post_list(request):
 qs = Post.objects.all()
 return render(request, "blog/post_list.html", {
 "post_list": qs,
 })
def post_detail(request, pk):
 post = get_object_or_404(Post, pk=pk)
 return render(request, "blog/post_detail.html", {
 "post": post,
 }

==============================================
서비스A에서 blog.urls를 include를 할 때 "blog/"를 prefix 주소로 쓰고 
서비스B에서는 "weblog/"를 prefix 주소로 쓴다 
=> prefix 로 쓰이는것을 url prefix라 한다 


 서비스A에서  mysite/urls.py
from django.urls import path, include
urlpatterns = [
 path("blog/", include("blog.urls")),
]

서비스B에서  mysite/urls.py
from django.urls import path, include
urlpatterns = [
 path("weblog/", include("blog.urls")),
]

이렇듯 장고의 강력한 URL reverse 기능 덕분에, 유리가 뷰코드나 HTML 테플릿에서 
뷰가 호출되기 위한 URL문자열을 하드코딩(Hard Coding)하는 것이아니라 
장고가 대신 URL문자열을 계산해주는 기능이 있다(이 기능이 URL Reverse)


==========================
엄격한 URL 패턴을 지정 
- URL문자열 패턴에 정규표현식을 지원하기에 엄격한 URL패턴이 가능
ex) 
/123/ 과 /about/ 주소를 서로 다른 뷰에 매칭할 수 있다
- 보통은 슬래시(/)를 구분자로 해서 둘 다 1씩이기 때문에, 두 주소를 같은 뷰/컨트롤러
에서 처리할 수 밖에 없다 
- 장고는 숫자만 들어가는 패턴과 숫자가 아닌 패턴을 구별할 수 있다 
- 그래서 숫자만 들어가는 문자열 패턴은 A라는 뷰, 그 외에는 B라는 뷰에서 처리하도록..

# blog/urls.py
from django.urls import re_path
urlpatterns = [
 # /blog/100/ ;Y8!éyoĺ, /blog/about/ |R!éyoÄ!ÅB!s· path rule!‚„Qº!‰rs.
 re_path(r"^(?P<pk>\d+)/$", views.post_detail),
 # /blog/about/ ;Y8! path rule|!éyoµ, page_detail tn!ÊÁoË page_name="about" ÈÍÎ!6¬n!Ï̉rs.
 re_path(r"^(?P<page_name>.+)/$", views.page_detail),
 re_path(r"^articles/(?P<year>\d{4})/$", views.year_archive),
=============================

모범 사례를 장려 
- 보다 가독성 높에 URL 패턴을 정의할 수 있도록 도와준다 
- path converter를 통해 간결하게URL패턴을 지정한다
- 웹페이지 URL에서 <파일 확장자>는 가급적 피한다(예시./blog/posts/100.html) 



from django.urls import include, path, re_path, register_converter
from .converters import FourDigitYearConverter
# –Â!!" path converters : str, int, slug, uuid, path
register_converter(FourDigitYearConverter, 'yyyy')
urlpatterns = [
 re_path(r"^(?P<pk>\d+)/$", views.post_detail),
 path("<int:pk>/", views.post_detail),
 re_path(r"^(?P<page_name>.+)/$", views.page_detail),
 path("<str:page_name>/", views.page_detail),
 re_path(r"^articles/(?P<year>\d{4})/$", views.year_archive),
 path("articles/<yyyy:year>/", views.year_archive),
]
# blog/converters.py
class FourDigitYearConverter:
 regex = r'\d{4}'
 def to_python(self, value):
 return int(value)
 def to_url(self, value):
 return '%04d' % valu

요청 URL은 단순히 문자열 
해당 veiw 함수가 호출되기 전 패턴에 부합되는 문자열만 뽑아내는 것을
캡처(Capture)라 한다 

=======================================

명확한 URL 

- foo.com/bar와 boo.com/bar/는 서로 다른 URL 
- 일반적인 django 구현에서는 끝이 슬래시(/)가 붙은 주소를 정의 
슬래시(/)가 붙지 않은 주소로 요청이 들어오면 슬래시(/)가 붙은 주소로 페이지 이동 
( 검색엔진이 혼동하지 않도록 URL를 정규화하는 옵션이 기본 활성화 )

- 만약 끝에 슬래시(/)가 붙지 않은 주소로 요청이 들어오면, 상태코드 301로서 
슬래시(/)가 붙은 주소로 이동하라 (301 Moved Permanetly)라는 응답을 한다