00 개요: urls.py, django.urls, django.conf.urls
1. urls.py의 역할
- Client가 웹서버의 하위 url에 접속할때 무엇을 보여줄 것인지(views) 정의하는 파일
- 해당 django 프로젝트/앱의 설정파일인 settings.py에서 ROOT_URLCONF을 이 파일(urls.py)로 잡음
ROOT_URLCONF = '앱이름.urls'
- 파일 내용 예
from django.urls import include, path from products.views import ProductsView urlpatterns = [ path('index/', views.index, name='main-view'), path('bio/<username>/', views.bio, name='bio'), path('articles/<slug:title>/', views.article, name='article-detail'), path('articles/<slug:title>/<int:section>/', views.section, name='article-section'), path('blog/', include('blog.urls')), path('products/', ProductsView.as_view()), ... ]
2. django.urls의 구성
- urls.py가 참조하는 django.urls 폴더는 다음과 같은 구조와 내용을 지님
-
lib > pyton3.6 > site-packages > django > urls > __pycache__ __init__.py # 중요 base.py conf.py # 중요 converters.py # 중요 exceptions.py resolvers.py utils.py
-
1) _init__.py 파일 내용
from .base import (
clear_script_prefix, clear_url_caches, get_script_prefix, get_urlconf,
is_valid_path, resolve, reverse, reverse_lazy, set_script_prefix,
set_urlconf, translate_url,
)
from .conf import include, path, re_path
from .converters import register_converter
from .exceptions import NoReverseMatch, Resolver404
from .resolvers import (
LocalePrefixPattern, ResolverMatch, URLPattern, URLResolver,
get_ns_resolver, get_resolver,
)
from .utils import get_callable, get_mod_func
__all__ = [
'LocalePrefixPattern', 'NoReverseMatch', 'URLPattern',
'URLResolver', 'Resolver404', 'ResolverMatch', 'clear_script_prefix',
'clear_url_caches', 'get_callable', 'get_mod_func', 'get_ns_resolver',
'get_resolver', 'get_script_prefix', 'get_urlconf', 'include',
'is_valid_path', 'path', 're_path', 'register_converter', 'resolve',
'reverse', 'reverse_lazy', 'set_script_prefix', 'set_urlconf',
'translate_url',
]
2) conf.py 파일 내용
"""Functions for use in URLsconfs."""
from functools import partial
from importlib import import_module
from django.core.exceptions import ImproperlyConfigured
from .resolvers import (
LocalePrefixPattern, RegexPattern, RoutePattern, URLPattern, URLResolver,
)
def include(arg, namespace=None):
app_name = None
if isinstance(arg, tuple):
# Callable returning a namespace hint.
try:
urlconf_module, app_name = arg
except ValueError:
if namespace:
raise ImproperlyConfigured(
'Cannot override the namespace for a dynamic module that '
'provides a namespace.'
)
raise ImproperlyConfigured(
'Passing a %d-tuple to include() is not supported. Pass a '
'2-tuple containing the list of patterns and app_name, and '
'provide the namespace argument to include() instead.' % len(arg)
)
else:
# No namespace hint - use manually provided namespace.
urlconf_module = arg
if isinstance(urlconf_module, str):
urlconf_module = import_module(urlconf_module)
patterns = getattr(urlconf_module, 'urlpatterns', urlconf_module)
app_name = getattr(urlconf_module, 'app_name', app_name)
if namespace and not app_name:
raise ImproperlyConfigured(
'Specifying a namespace in include() without providing an app_name '
'is not supported. Set the app_name attribute in the included '
'module, or pass a 2-tuple containing the list of patterns and '
'app_name instead.',
)
namespace = namespace or app_name
# Make sure the patterns can be iterated through (without this, some
# testcases will break).
if isinstance(patterns, (list, tuple)):
for url_pattern in patterns:
pattern = getattr(url_pattern, 'pattern', None)
if isinstance(pattern, LocalePrefixPattern):
raise ImproperlyConfigured(
'Using i18n_patterns in an included URLconf is not allowed.'
)
return (urlconf_module, app_name, namespace)
def _path(route, view, kwargs=None, name=None, Pattern=None):
if isinstance(view, (list, tuple)):
# For include(...) processing.
pattern = Pattern(route, is_endpoint=False)
urlconf_module, app_name, namespace = view
return URLResolver(
pattern,
urlconf_module,
kwargs,
app_name=app_name,
namespace=namespace,
)
elif callable(view):
pattern = Pattern(route, name=name, is_endpoint=True)
return URLPattern(pattern, view, kwargs, name)
else:
raise TypeError('view must be a callable or a list/tuple in the case of include().')
path = partial(_path, Pattern=RoutePattern)
re_path = partial(_path, Pattern=RegexPattern)
3) converters.py 파일 내용
import uuid
from functools import lru_cache
class IntConverter:
regex = '[0-9]+'
def to_python(self, value):
return int(value)
def to_url(self, value):
return str(value)
class StringConverter:
regex = '[^/]+'
def to_python(self, value):
return value
def to_url(self, value):
return value
class UUIDConverter:
regex = '[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}'
def to_python(self, value):
return uuid.UUID(value)
def to_url(self, value):
return str(value)
class SlugConverter(StringConverter):
regex = '[-a-zA-Z0-9_]+'
class PathConverter(StringConverter):
regex = '.+'
DEFAULT_CONVERTERS = {
'int': IntConverter(),
'path': PathConverter(),
'slug': SlugConverter(),
'str': StringConverter(),
'uuid': UUIDConverter(),
}
REGISTERED_CONVERTERS = {}
def register_converter(converter, type_name):
REGISTERED_CONVERTERS[type_name] = converter()
get_converters.cache_clear()
@lru_cache(maxsize=None)
def get_converters():
return {**DEFAULT_CONVERTERS, **REGISTERED_CONVERTERS}
def get_converter(raw_converter):
return get_converters()[raw_converter]
3. django.conf.urls의 구성
- urls.py가 참조하는 django.urls 폴더는 다음과 같은 구조와 내용을 지님
-
lib > pyton3.6 > site-packages > django > conf > urls > __pycache__ __init__.py # 중요 i18n.py static.py # 중요
-
1) _init__.py 파일 내용
import warnings
from django.urls import include, re_path
from django.utils.deprecation import RemovedInDjango40Warning
from django.views import defaults
__all__ = ['handler400', 'handler403', 'handler404', 'handler500', 'include', 'url']
handler400 = defaults.bad_request
handler403 = defaults.permission_denied
handler404 = defaults.page_not_found
handler500 = defaults.server_error
def url(regex, view, kwargs=None, name=None):
warnings.warn(
'django.conf.urls.url() is deprecated in favor of '
'django.urls.re_path().',
RemovedInDjango40Warning,
stacklevel=2,
)
return re_path(regex, view, kwargs, name)
2) static.py 파일 내용
import re
from urllib.parse import urlsplit
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.urls import re_path
from django.views.static import serve
def static(prefix, view=serve, **kwargs):
"""
Return a URL pattern for serving files in debug mode.
from django.conf import settings
from django.conf.urls.static import static
urlpatterns = [
# ... the rest of your URLconf goes here ...
] + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
"""
if not prefix:
raise ImproperlyConfigured("Empty static prefix not permitted")
elif not settings.DEBUG or urlsplit(prefix).netloc:
# No-op if not in debug mode or a non-local prefix.
return []
return [
re_path(r'^%s(?P<path>.*)$' % re.escape(prefix.lstrip('/')), view, kwargs=kwargs),
]
01 path( )
- 기능: URL경로(route)를 views 함수(view)에 전달
from django.urls import path
path(route, view, kwargs=None, name=None)
- 사용 예
from django.urls import include, path urlpatterns = [ path("index/", views.index, name="main-view"), path("bio/<username>/", views.bio, name="bio"), path("articles/<slug:title>/", views.article, name="article-detail"), path("articles/<slug:title>/<int:section>/", views.section, name="article-section"), path("blog/", include("blog.urls")), ..., ]
- return 값: urlpattern에 들어갈 요소
- parameters:
- route (required): str 또는 gettext_lazy( ) 자료형의 URL pattern
- route가 빈 따옴표('')면 root url을 의미
- URL 일부를 캡쳐해서 keyword argument로 view에 보내는 역할을 하는 angle brackets (<keyword argument>) 포함 가능
- view (required): views.함수명 또는 클래스명.as_view() 또는 django.urls.include( )
- Function-Based View의 경우 views.함수명 (i.e., view 함수)
- Class-Based View의 경우 클래스명.as_view( ) (i.e., as_view( )의 결과값)
- kwargs (optional): view function이나 method에 넣을 dict 자료형의 추가적인 인자
- name (optional): 해당 URL pattern에 사용할 str 자료형의 urlpattern 이름
- URL reversing을 하려면 URL pattern의 이름을 정해줘야 함
- 즉, URL별로 변수를 만들어 활용하는 경우 사용
- route (required): str 또는 gettext_lazy( ) 자료형의 URL pattern
- converter로 제한 (converter specification)
- converter specification을 통해 매칭되는 characters를 제한하고 view에 전달되는 변수의 타입 변경 가능
- <converter:전달할keyword_argument명> 로 입력시 입력받는 데이터를 제한 가능
- converter 종류
- str : 경로 구분자를 제외한 비어 있지 않은 문자열
- path: 경로 구분자를 포함한 비어 있지 않은 문자열
- int : 0 또는 임의의 양의 정수
- slug : 문자 또는 숫자와 하이픈 및 밑줄 문자로 구성된 슬러그 문자열 (예: SHOW-ME-THE-MONEY)
- 사용 예
# urls.py ... 생략 urlpatterns = [ ... 생략 path('<username>/<int:articleId>', views.get_user_article), ]
# views.py ...생략 def get_user_article(request, username, articleId): print("username : ", username) print("articleId", articleId) return HttpResponse("{}의 블로그 {}번 글이 출력됩니다!".format(username, articleId)) ... 생략
- 테스트 서버를 실행하여 아래 경로로 들어가보기:
- http://127.0.0.1:8000/path/suwoni/1
- http://127.0.0.1:8000/path/suwoni/03
- http://127.0.0.1:8000/path/suwoni/test
- 결과:
- 첫번째, 두번째는 정상적으로 화면 출력됨
- 두번째는 03이 3으로 변환되어 출력됨
- 세번째는 int타입이 아닌 test문자열로 인해 Page not found(404) 에러 발생
- 테스트 서버를 실행하여 아래 경로로 들어가보기:
02 re_path( )
- 기능: 정규식으로 표현된 URL경로(route)를 views 함수(view)에 전달
- NOTE:
- django 2.0에서 새롭게 추가된 함수
- django 2.0 이전에 사용하던 url 함수와 동일
from django.urls import re_path
re_path(route, view, kwargs=None, name=None)
- 사용 예
from django.urls import include, re_path urlpatterns = [ re_path(r"^index/$", views.index, name="index"), re_path(r"^bio/(?P<username>\w+)/$", views.bio, name="bio"), re_path(r"^blog/", include("blog.urls")), ..., ]
- return 값: urlpattern에 들어갈 요소
- parameters:
- route: str 또는 gettext_lazy() 자료형의 Python 의 re 모듈 정규식
- 기호 종류
- ^: 정규식 시작
- $: 정규식 종료
- r: escape
- str은 raw string syntax (r' ') 을 사용
- 이때 \d의 escape 를 위한 \ 가 추가로 필요하지 않음
- match 성공시 정규식(regular expression)으로 캡쳐된 group은 (이름이 지정된 경우) 이름이 지정된 인자 또는 (이름이 지정되지 않은 경우) positional 인자로 view에 str으로 전달됨
- route 가 $로 끝나는 경우 전체 요청 URL은 regular expression pattern 과 일치해야 함 (re.fullmatch() 사용)
- 기호 종류
- view: view function 또는 (class-based view 의 경우) as_view() 의 결과값 또는 django.urls.include()
- kwargs: view function이나 method에 넣을 추가적인 인자
- name: 해당 URL pattern에 사용할 str 자료형의 urlpattern 이름
- URL reversing을 하려면 URL pattern의 이름을 정해줘야 함
- route: str 또는 gettext_lazy() 자료형의 Python 의 re 모듈 정규식
03 include( )
- 기능: 다른 app의 urls.py (URLconf 모듈)를 연결/포해주는 함수
from django.urls import include
# 3가지 방법
include(module, namespace=None)
include(pattern_list)
include((pattern_list, app_namespace), namespace=None)
- 사용 예
from django.conf.urls import url url(r'^dcv/account/', include('allauth.urls'))
- parameters:
- module (required): URLconf 모듈 (또는 모듈명)
- namespace (optional): str 자료형의 instance namespace for the URL entries being included
- Optionally, the application namespace and instance namespace where the entries will be included into can also be specified.
- Usually, the application namespace should be specified by the included module. If an application namespace is set, the namespace argument can be used to set a different instance namespace.
- pattern_list: iterable of path() and/or re_path() instances
- app_namespace : str 자료형의 application namespace for the URL entries being included
04 register_converter()
- 기능: registers a converter for use in path() routes
register_converter(converter, type_name)
- 사용 예
from django.urls import path, register_converter from . import converters, views register_converter(converters.FourDigitYearConverter, "yyyy") urlpatterns = [ path("articles/2003/", views.special_case_2003), path("articles/<yyyy:year>/", views.year_archive), ..., ]
- 파라미터:
- converter: converter class
- type_name: path pattern에 사용할 str 자료형의 converter 이름
05 static( )
- 기능: Helper function to return a URL pattern for serving files in debug mode
from django.conf.urls.static import static
static(prefix, view=django.views.static.serve, **kwargs)
- 사용 예
from django.conf import settings from django.conf.urls.static import static urlpatterns = [ # ... the rest of your URLconf goes here ... ] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
2024.03.20 - [분류 전체보기] - Django Static 파일 관리하기 (image, JavaScript, CSS, etc.)
참조
- https://docs.djangoproject.com/en/5.0/ref/urls/
- https://holsui.tistory.com/98
- https://velog.io/@stresszero/%EC%9E%A5%EA%B3%A0-URL-%EC%A0%95%EB%A6%AC
- https://suwoni-codelab.com/django/2018/03/23/Django-Url-function/
- https://docs.djangoproject.com/en/5.0/howto/static-files/
'Web 개발 > Django' 카테고리의 다른 글
QuerySet API (쿼리셋 API) (0) | 2024.03.25 |
---|---|
Django의 values() vs values_list() (0) | 2024.03.25 |
Django Static 파일 관리하기 (image, JavaScript, CSS, etc.) (0) | 2024.03.20 |
Django (0) | 2024.03.18 |