[Django] URL
작성:    
업데이트:
카테고리: Django
태그: BE Framework, Django
URL
- Dispatcher(발송자, 운항 관리자)로서의 URL
- 웹App은 URL을 통한 클라이언트의 요청으로부터 시작
Variable Routing
- URL 주소를 변수로 사용
- URL의 일부를 변수로 지정 → view 함수의 인자로 전달 가능
- 변수 값에 따라 하나의 path()에 여러 페이지(개별 페이지) 연결 가능
- 사용자/컨텐츠에 따른 개별적인 페이지!! → 동적 웹 프로그래밍
- 꺽쇠(<>; angle bracket)로 표시
사용 예시
path('accounts/user/`<int:user_pk>`/', ...)
- accounts/user/1 → 1번 유저 관련 페이지
- accounts/user/2 → 2번 유저 관련 페이지
URL Path converters
- variable routing을 통해 url에 변수처럼 들어오는 것을 형변환
- int:, str: 등이 있다.
path('something/<???:name>', views.something)
str
- ’/’를 제외하고 비어있지 않은 모든 문자열과 매치
- converter 부분을 명시하지 않을 경우 기본적으로 str
int
- 0 또는 양의 정수와 매치
- 문자열, 소수의 경우 사용 시 오류
사용 예시
# urls.py
urlpatterns = [
...
path('hello/<name>/<int:nums>', views.hello)
]
- urls.py에서 server로 전송된 url 확인
- 함수와 매핑할 url 형식 지정
# views.py
def hello(request, name, nums):
context = {
'name':name,
'nums':nums,
}
return render(request, 'hello.html', context)
- 기본 url 뒤의 router variables는 함수의 parameter로 전달
<!-- hello.html -->
{% extends 'base.html' %} {% block content %}
<h1>HELLO {{ name }}!!</h1>
<h2> {{ nums }}명 </h2>
{% endblock content %}
- html 템플릿에서 변수로 사용
주의📢 url path converter의 경우 urls.py에서 순서를 잘 설정해주어야 한다!
# urls.py
urlpatterns = [
path('<name>/', views.hello),
path('index/', views.index),
path('menus/', views.menus),
]
url path converter가 들어있는 path의 순서가 위쪽으로 가게 되면, 이후에 비슷한 형식을 가진 raw value들은 사용할 수 없다!
App URL mapping
- app의 view 함수가 많아지면서 사용하는 path()이 많아진다.
- 프로젝트의 urls.py에서 모두 관리하는 것은 유지보수에 좋지 않다.
Sol : 각 app의 urls.py을 만들고 함수가 아닌 app의 경로를 include!
- 지금까지는 pjt에서 pjt 내의 views.py의 함수를 매핑
- 프로젝트의 경로를 ‘pages/’로 들어오면 ‘pages’ app으로 이후의 url을 전달
- App의 urls.py에서 이후의 url을 더 분석하여 처리
# firstpjt/urls.py
from django.contrib import admin
from django.urls import path, include
urlpatterns = [
path('admin/', admin.site.urls),
path('articles/', include('articles.urls')),
path('pages/', include('pages.urls')),
]
include()
- 다른 URLconf들을 참조할 수 있도록 한다.
- URL의 해당 시점까지 일치하는 부분을 제외하고 남은 문자열 부분을 include된 URLconf로 전달
- django는 명시적 상대경로(from
<module>
import<function or variables>
)를 권장
Naming URL patterns
- 지금까지는 링크에 url을 직접 작성
-
이제는 path() 함수의 name 인자를 정의해서 사용
- django template tag 중 하나인 url 태그({% url ‘path name’ %})를 사용
- path() 함수에 작성한 name 사용 가능
# urls.py
urlpatterns = [
path('index/', views.index, name='index'),
]
url, 매핑 함수, 이후에 name 설정
<a href="{% url 'index' %}">메인 페이지</a>
- 자세한 특징은 아래에 후술
url template tag
{% url 'path name' %}
- 주어진 URL 패턴 이름 및 선택적 매개 변수와 일치하는 절대 경로 주소 반환
- 템플릿에 URL을 하드 코딩하지 않고도 DRY 원칙(Don’t Repeat Yourself)을 위반하지 않으면서 링크 출력
- url 설정에 정의된 특정한 경로들의 의존성 제거 가능
- DRY 원칙: Don’t Repeat Yourself
파일명 중복 대응 : Namespace
- django의 파일 조회 순서
- [settings.py]-[TEMPLATES]-[DIRS]에 지정해둔 경로의 html 템플릿
- [settings.py]-[INSTALLED_APPS]에 지정해둔 각 App들의 html 템플릿
- django는 extends나 file_name/ 사용 시 등록된 경로는 제외하고 바로 갖다 붙인 것을 한 번에 모은다.
- **파일명이 같으면 지정된 경로 우선순위대로 앞에 경로가 붙어버린다.
- 다른 app이어도 같은 파일명을 사용한다면 다른 파일이 렌더링 될 수 있다.
Sol : app들마다 templates 폴더 내에 app 이름의 폴더를 만들고 그 안에 template html 파일을 넣자!
- 경로를 물리적으로 구분해서 설정해주는 것이다.
- 이렇게 만들어준 물리 경로가 namespace가 되는 것!
# pages/views.py
from django.shortcuts import render
def index(request):
return render(request, 'pages/index.html')
- 이후 경로를 app이름(templates 내의 폴더 이름)으로 설정하면 되겠다.
- 같은 파일명이어도 경로를 명시함으로써 다른 파일임을 확실히 명시하는 것.
url tag에서는?
articles app의 index.html에서 pages app의 index.html을 연결하려면 url tag는 어떻게 쓰나요?
<!-- articles/index.html -->
{% extends 'base.html' %}
{% block content %}
<h1>안녕하세요ㅎㅎ</h1>
<a href="/articles/greeting/">greeting</a> | 🔸 url 태그에 절대 경로를 hard coding한 예
<a href="{% url 'dinner' %}">dinner</a> |
<a href="{% url 'dtl-practice' %}">dtl-practice</a> |
<a href="{% url 'throw' %}">throw</a> |
<a href="{% url 'index' %}">Page Index</a> ⭐ 목표하는 다른 app의 파일
{% endblock content %}
dinner, dtl-practice, throw 같은 경우 articles 앱의 templates 내의 html 파일이므로 바로 사용할 수 있었다. 그런데 page는 다른 app인데 다른 app의 경로를 url tag로 어떻게 쓸 수 있을까?
URL namespace
<!-- articles/index.html -->
{% extends 'base.html' %}
{% block content %}
<h1>안녕하세요ㅎㅎ</h1>
<a href="/articles/greeting/">greeting</a> |
<a href="{% url 'articles:dinner' %}">dinner</a> |
<a href="{% url 'articles:dtl-practice' %}">dtl-practice</a> |
<a href="{% url 'articles:throw' %}">throw</a> |
<a href="{% url 'pages:index' %}">Page Index</a> ⭐
{% endblock content %}
- ‘어느 app의 path name이다’라는 것이 명시되면 좋겠다..!
app_name
urls.py 파일 내에서 경로를 설정해주듯이 app_name:을 앞에 붙여 어느 app의 path name인지를 명시해준다.
- 같은 앱 내부에서 사용되는 path여도 app_name을 명시해주자.
# pages/urls.py
app_name = 'pages'
urlpatterns = [
path('index/', views.index, name='index'),
]
app_name을 app 이름으로 설정해야 위와 같은 작업이 가능하다.
댓글남기기