Django의 URL namespace
URL Namespace
우리의 프로젝트는 article과 user 두개의 앱을 가지고 있다.
우리는 url name을 참조하여 실제 url을 찾아가도록 하는데,
만약 두개의 앱에서 같은 name을 쓴다면 어떻게 될까?
(articles/urls.py에도 hello/ url이 있고, users/urls.py에도 hello/가 있다면?)
articles/urls.py
from django.urls import path
from . import views
urlpatterns = [
...
path("hello/", views.hello, name="hello"),
...
]
users/urls.py
from django.urls import path
from . import views
urlpatterns = [
...
path("hello/", views.hello, name="hello"),
...
]
⇒ 둘다 hello라는 url name을가지고, 인덱스에서 해봤더니 항상 articles의 앱으로 간다.
왜?
setting.py의 installed_apps의 순서에 비밀이 있다.
장고는 여기 적혀있는 순서대로 모든 것을 찾는다.(url, templates .... 모두)
두개 순서를 바꾼다음에 해보면 users/hello로 간다.
😗 hello/는 동일하지만 하나는 articles/hello/, 다른 하나는 users/hello/라서 다른데 이 정도는 구분하지 않을까요?
그런데 만약
⇒ 그러니까 url namespce를 적용해봅시다!{% url 'hello' %} # 어디로 가죠? redirect('hello') # 어디로 가야할까요?
index, create 같은 것들은 겹칠 가능성이 많겠죠?
항상 article_create, user_create처럼 해줘도되겠지만 귀찮죠?
→ 네임스페이스 만든다.
그안에서 url관리하도록 한다.
(먼저 네임스페이스를 보고, 그다음에 url 보도록 → url이 같아도 네임스페이스가 다르니 괜찮아진다.)
URL Namespace
- Django는 서로 다른 앱에서 동일한 URL Name을 사용하는 경우, 고유하게 구분할 수 있도록 namespace를 지원합니다.
from django.urls import path
from . import views
app_name = "articles"
urlpatterns = [
...
path("hello/", views.hello, name="hello"),
...
]
url에 이름공간을 만들어주고 나면, namespace:url_name형태로 사용합니다.
{% url 'articles:hello' %}
redirect('articles:hello')
→ app_name = "articles" 해주면 이 문장 써주는 순간 네임스페이스 적용
→ 이제 url pattern에서 사용하는 이름들은
templates에서 이제는 {% url 'hello' %} 가 아닌 {% url 'articles:hello' %} 이런식으로 참조해줘야한다.
프로젝트 처음에 만들 때부터 이렇게 해주자.
에러 발생
- 이전의 형태로 사용하면 에러가 발생합니다.
- 수정하기
articles
users
{% url 'profile' %} -> {% url 'users:profile' %}
redirect('profile') -> redirect('users:profile')
views의 redirect도 articles 말고 articles:articles로 해주자
namespace를 준 순간,
그냥 create적으면 안되고 appname:create해줘야한다.
안그러면 에러남.
만약 articles의 hello.html 파일을 지워버린다면?
users의 hello.html로 간다.
→ installed_apps 순서대로 다 뒤져보고 "articles",도 없으니 "users",로 간 것!
Templates 구조
만약, 내가 똑같은 이름의 템플릿을쓰고싶다면?
템플릿도 url처럼 namespace같은 형식을 만들수는 없을까?
현재 우리는
"index.html"만 적어주면 django가 알아서 찾아옵니다.
만약, users앱에도 index.html이 있고 articles앱에도 index.html 이 있다면 어떻게 될까요?
{% extends "base.html" %}
{% block content %}
<h1>여기는 Users App의 INDEX</h1>
{% endblock %}
users/templates/index.html
/index/로 들어가보면,
⇒ 오, django가 똑똑하게 잘 가져오고 있는데요?!
그런데 이렇게 바꾸면 어떻게 될까요?
다시 /index/로 들어가보면,
⇒ 즉, Django는 Apps를 하나씩 돌면서 App 안에 templates가 있으면 들어가서 이름과 일치하는 템플릿을 꺼내오는 로직을 반복하는 것입니다!
→ 그럼 매번 우리가 App 순서를 신경쓰면서 작업해야 할까요? 😭
장고에서 권장하는 구조는
app이름의 디렉토리 안쪽에 / 템플릿/ 앱네임 / html파일들
→ 햄버거같은 구조!
Templates Namespace 만들어주기
- <app_name>/templates/<app_name>으로 구조 만들기
→ 그리고 이제부터 view에서 템플릿을 사용할 때는 <app_name>/template.html 으로 사용하면 됩니다!
(articles/index.html 이런식)
users앱도 같은 방법으로 해주자
프로젝트 처음부터 이런 식으로 작성해 주자.