Django 2.x. Migrujemy z url() na path()

2 minut(y)

url() vs path()

Jedną z bardziej znaczących zmian, które zostały wprowadzone w wersji Django 2.0 w stosunku do wersji wcześniejszych jest zmiana (a raczej rozbudowa) sposobu definiowania szablonów URL. W Django w wersjach 1.x używaliśmy funkcji url(), której przekazywaliśmy wyrażenie regularne z nazwanymi grupami aby UrlResolver mógł na jego podstawie rozpoznać parametry adresu URL:

url(r'^books/(?P<book_id>[0-9]+)/$', book_detail_view)

W wersji Django 2.x możemy używać funkcji patch() której przekazujemy łańcuch znaków zamiast wyrażenia regularnego.

path('books/<int:book_id>/', book_detail_view)

Dla tych, którzy nadal chcę używać wyrażeń regularnych udostępniono funkcję re_path(), która działa identycznie jak url() we wcześniejszych wersjach Django, a na razie sama funkcja url() nadal jest dostępna do użycia.

Zwrócić należy uwagę, że łańcuch ze ścieżką w path() zawsze odnosi się do całej ścieżki, a nie do jej fragmentu path(‘accounts/login’) odpowiada url(r’^accounts/login/$’)

Fragmenty łańcucha ścieżki ujęte w ostrych nawiasach <int:book_id> służą do wyodrębniania parametrów, które są następnie przekazywane do widoku. Pierwsza część (po lewej stronie znaku ‘:’) to tzw konwerter ścieżki (path converter). Konwerter ma za zadanie dokonać konwersji parametru do określonego typu przed przekazaniem go do widoku. Druga część (na prawo od znaku ‘:’) to nazwa tego parametru, pod którą jego wartość będzie on dostępna w widoku.

Wcześniejsze wersje Django wyodrębnione parametry zawsze przekazywały do widoku jako łańcuch znaków (str). Taka sytuacja ma miejsce obecnie również w przypadku wspomnianej wcześniej metody re_path() (lub url())

Wbudowane konwertery

W Django 2.x mamy do dyspozycji pięć wbudowanych konwerterów:

int

  • Dodatnia wartość całkowita większa lub równa 0, np. ‘7463’
  • Przekazywany do widoku jako (int)
  • Odpowiednik [0-9]+ lub [\d]+

str

  • Dowolny niepusty ciąg znaków z wyłączeniem znaku /, np ‘inactive’
  • Przekazywany do widoku jako łańcuch znaków (str)
  • Odpowiednik [^/]+

slug

  • Ciąg znaków który może się składać z liter, cyfr, znaku ‘-‘ lub znaku ‘_’, np ‘czerwona-torebka-z-naszywka’
  • Przekazywany do widoku jako łańcuch znaków (str)
  • Odpowiednik [-a-zA-Z0-9_]+

uuid

  • Ciąg znaków odpowiadający sformatowanemu UUID (z kreskami i małymi literami). np ‘d8a6f1b2-adca-4b11-ad42-f99d8ffccc26’
  • Przekazywany do widoku jako instancja UUID (uuid.UUID)
  • Odpowiednik [0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}

path

  • Dowolny niepusty ciąg znaków włączając znak /, np ‘/path/to/file/pdf’
  • Przekazywany do widoku jako łańcuch znaków (str)
  • Odpowiednik ’.+’

Własne konwertery

Jeśli dla kogoś liczba i zakres dostępnych konwerterów jest niewystarczający może stworzyć i zarejestrować własny konwerter. Jest to bardzo proste. Najpierw piszemy kod klasy konwertera zawierający die metody to_python() i to_url():

# converters.py

class YearConverter:
  regex = '[0-9]{4}'

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

  def to_url(self, value):
    return f'{value:04d}'

następnie rejestrujemy konwerter przed jego użyciem:

# urls.py
from django.urls import path, register_converter
from . import views, converters

register_converter(converters.YearConverter, 'year')

urlpatterns = [
  ...
  path('list/<year:year>', view=views.YearArchiveView.as_view(), name='year_archive'),
]

To oczywiście nie wyczerpuje tematu konwerterów, gdyż możliwości ich wykorzystania jest znacznie więcej. Przykłdem niech będzie pakiet dla Django django-model-path-converter, który pozwala dynamicznie tworzyć własne ścieżki dla własnych modeli.

Zostaw komentarz