Python
Django
Django2.0

【django2.0】便利なパスコンバータのご紹介

Djangoもくもく会 #04 in 御徒町 で少し話題になった内容です。

django2.0の新機能「パスコンバータ」

djangoでURLのルーティングを記述するとき、django1.x系では正規表現を用いていました

old_urls.py
urlpatterns = [
    url(r'^[0-9]+/$', views.integer, name="integer")
    url(r'^[a-zA-Z]+/$', views.string, name="string")
]

django2.0では、新たに追加された「パスコンバータ」を用いてルーティングを記述できるようになりました!

new_urls.py
urlpatterns = [
    path('<int>/', views.integer, name="integer")
    path('<slug>/', views.string, name="string")
]

ざっくりな使い方

new_urls.py
urlpatterns = [
    # 整数がマッチした場合
    path('<int>/', views.integer, name="integer")
    # url(r'^[0-9]+/$', views.integer, name="integer")と等価

    # 整数がマッチした場合、viewsのintegerの引数にvalueを代入(以下同様)
    path('<int:value>/', views.integer, name="integer")
    # url(r'^?P<value>\[0-9]+/$', views.integer, name="integer")と等価

    # 文字列(/を除く)がマッチした場合
    path('<str>/', views.string, name="string")
    # url(r'^[^/]+/$', views.string, name="string")と等価

    # slug(半角小大英数字とハイフンとアンダースコア)がマッチした場合
    path('<slug>/', views.slug, name="slug")
    # url(r'^[-a-zA-Z0-9_]+/$', views.slug, name="slug")と等価

    # UUID(8-4-4-12の半角小英数字)がマッチした場合
    path('<uuid>/', views.uuid, name="uuid")
    # url(r'^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/$', views.uuid, name="uuid")と等価

    # URLがマッチした場合
    path('<path>/', views.path, name="path")
    # url(r'^.+/$', views.path, name="path")と等価
]

自作も可能

さらにこのパスコンバータは自分で定義することも可能で

new_converter.py
class FourDigitYearConverter:
    regex = '[0-9]{4}'

    def to_python(self, value):
        return int(value)

    def to_url(self, value):
        return '%04d' % value

と定義したのちに、urls.pyにて

urls.py
from django.urls import register_converter, path
from . import converter, views

# ここで定義したパスコンバータを有効化
register_converter(converter.FourDigitYearConverter, 'year')

urlpatterns = [
    path('articles/<year:year>/', views.year_archive),
    ...
]

とすれば、おk
(ソースコード引用:https://docs.djangoproject.com/en/2.0/topics/http/urls/)

まとめ

django2.0からは、ルーティングが楽になる「パスコンバータ」が導入されました。
これで面倒な正規表現のコピー&ペースト作業が減りますね