djangoのurl, pathについて

Django初心者です。


Django2系を書いていると、urls.pyに出てくる

```python: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には

```python: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系では
```python:urls.py
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),
]
```
という感じかけるようになっています。

[Django 2.0 release notes](https://docs.djangoproject.com/es/2.0/releases/2.0/)によると

>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<year>[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に置き換わっていました。

https://github.com/django/django/blob/master/django/conf/urls/__init__.py

じゃあ、pathとre_pathの違いはなんだろう？
djangoのconf.py, resolver.pyをみてみます

https://github.com/django/django/blob/master/django/urls/resolvers.py

```python:django/conf.py
path = partial(_path, Pattern=RoutePattern) 
re_path = partial(_path, Pattern=RegexPattern) 
```

Patternの違いっぽいですね。最終的に、_pathはURLResolverを返すので、その辺をみて見ると、冒頭にmatchメソッドが使われています。
簡単に、matchメソッドで比べて見ると、

```python:RoutePattern
    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に戻して返す

```python:RegexPattern
    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の方が楽だしそっちを使おうかなあ、とか思っています
もっと詳しい方色々教えてください