Django初心者です。
Django2系を書いていると、urls.pyに出てくる
The `urlpatterns` list routes URLs to views. For more information please see:
https://docs.djangoproject.com/en/2.0/topics/http/urls/
Examples:
Function views
1. Add an import: from my_app import views
2. Add a URL to urlpatterns: path('', views.home, name='home')
Class-based views
1. Add an import: from other_app.views import Home
2. Add a URL to urlpatterns: path('', Home.as_view(), name='home')
Including another URLconf
1. Import the include() function: from django.urls import include, path
2. Add a URL to urlpatterns: path('blog/', include('blog.urls'))
"""
が気になって、少し調べてみました。
Django1系ではどう書くか
djangoのチュートリアルとかをやると、urls.pyには
from django.contrib import admin
from django.conf.urls import url, include
urlpatterns = [
url('', include('myapp.urls'))
url(r'^admin/', admin.site.urls),
]
みたいに書くことがあると思います。
urlpatternで、adminとかmyapp.urlsで指定されているテンプレートを展開する処理です。
Django2系では
from django.contrib import admin
from django.urls import path, include, re_path
urlpatterns = [
path('', include('myapp.urls'))
re_path(r'admin/', admin.site.urls),
]
という感じかけるようになっています。
Simplified URL routing syntax¶
The new django.urls.path() function allows a simpler, more readable URL routing syntax. For example, this example from previous Django releases:
url(r'^articles/(?P[0-9]{4})/$', views.year_archive),
could be written as:
path('articles/int:year/', views.year_archive),
The new syntax supports type coercion of URL parameters. In the example, the view will receive the year keyword argument as an integer rather than as a string. Also, the URLs that will match are slightly less constrained in the rewritten example. For example, the year 10000 will now match since the year integers aren’t constrained to be exactly four digits long as they are in the regular expression.
The django.conf.urls.url() function from previous versions is now available as django.urls.re_path(). The old location remains for backwards compatibility, without an imminent deprecation. The old django.conf.urls.include() function is now importable from django.urls so you can use from django.urls import include, path, re_path in your URLconfs.
The URL dispatcher document is rewritten to feature the new syntax and provide more details.
とのことです。ざっくりと和訳すると
- もっとシンプルで、読みやすいurlルーティングを作った。
- pathは型強制(Type Hintsみたいなものかな)をサポートしている
- 昔のやつは後方互換性のために残していて、すぐに消したりはしない
- django.conf.urls.url() == django.urls.re_path()
- includeもdjango.urlsに入っている
って感じみたいです。
中身は?
githubのdjangoをみて見ると、すでにdjango.conf.urlsのurlはre_pathに置き換わっていました。
じゃあ、pathとre_pathの違いはなんだろう?
djangoのconf.py, resolver.pyをみてみます
path = partial(_path, Pattern=RoutePattern)
re_path = partial(_path, Pattern=RegexPattern)
Patternの違いっぽいですね。最終的に、_pathはURLResolverを返すので、その辺をみて見ると、冒頭にmatchメソッドが使われています。
簡単に、matchメソッドで比べて見ると、
def __init__(self, route, ...):
...
self.converters = _route_to_regex(str(route), is_endpoint)[1]
def match(self, path):
match = self.regex.search(path)
if match:
# RoutePattern doesn't allow non-named groups so args are ignored.
kwargs = match.groupdict()
for key, value in kwargs.items():
converter = self.converters[key]
try:
kwargs[key] = converter.to_python(value)
except ValueError:
return None
return path[match.end():], (), kwargs
return None
RoutePatternはurlpatternを渡して、正規表現に一度変換して、UUIDに戻して返す
def match(self, path):
match = self.regex.search(path)
if match:
# RoutePattern doesn't allow non-named groups so args are ignored.
kwargs = match.groupdict()
for key, value in kwargs.items():
converter = self.converters[key]
try:
kwargs[key] = converter.to_python(value)
except ValueError:
return None
return path[match.end():], (), kwargs
return None
RegexPatternは、渡した正規表現でマッチングして返すみたいな感じの実装になっているのかな?
※やや頭が混乱してきました。
まとめ
あんまり私はこの辺詳しくないので、大したことは言えませんがpath, re_pathどちらで渡しても結局正規表現でマッチングしてくれるようです。
なので、僕はpathの方が楽だしそっちを使おうかなあ、とか思っています
もっと詳しい方色々教えてください