17 czerwca 2019

Ustawienie adresów url w Django

O adresach url w django pisałem już tutaj, ale temat jest obszerniejszy i zasługuje na osobny wpis.

Wszystko ma swój początek w pliku „urls.py„. Tutaj ustawiamy adresy dla naszej aplikacji.

Ustawienie prostego adresu url w django

Aby ustawić pierwszy adres url w django, wystarczy wpisać prostą regułę:

path('adres', views.metoda, name='nazwa')

Pamiętaj jednak, aby wcześniej zaimportować funkcję path:

from django.urls import path

Powyższy wzór przedstawia wam sposób w jaki możemy ustawić prosty adres dla naszej aplikacji.

Wywołujemy funkcję o nazwie „path” i podajemy kolejno parametry takie jak:

  1. Wzorzec adresu
  2. Funkcja wywołana po wpisaniu adresu pasującego do wzorca
  3. Nazwa adresu (w celu ustawienia odnośników w aplikacji)

Poniżej przykład zapisanego prostego adresu opierając się o powyższy wzór:

urlpatterns = [
    path('list', views.list, name='list'))
]

Powyższy adres będzie miał za zadanie wyświetlenie nam jakiejś listy. Co istotne kolejne adresy zapisujemy w postaci elementów listy o nazwie „urlpatterns„.

Zmienne w adresach url django

Co w sytuacji gdy chcieli byśmy pokazać konkretny wpis zamiast całej listy ?

Powiedzmy, że znamy numer id wpisu, ale nie będziemy przecież podawać wszystkich możliwości w „urlpatterns” podając kolejno liczby od 0 do X.

Musimy w takiej sytuacji powiadomić django, że w adresie url może pojawić się niewiadoma która jest liczbą.

path('poczatek_adresu/<typ:nazwa_zmiennej>/', views.metoda, name='nazwa')

Powyższy wzór pomoże nam w zrozumieniu w jaki sposób powinniśmy obsłużyć możliwość podania zmiennej w adresie url.

W django mamy możliwość podania jakiego typu zmienna może zostać w adresie użyta aby pasowała do wzoru. Zapoznaj się z poniższą listą typów zmiennych:

  • str – Dowolny ciąg znaków poza znakiem „/”.
  • int – Dowolna dodatnia liczba całkowita.
  • slug – Ciąg znaków zbudowany z cyfr, liczb, znaku podkreślenia oraz myślnika
  • uuid – Ciąg znaków zgodny z wzorcem uuid, składający się z małych liter, myślników oraz cyfr
  • path – Jest to podobny typ jak „str” jednak może zawierać w sobie znak „/”

Możemy na podstawie powyższej listy ustawić wzór adresu url:

path('user/<int:id>', views.account, name='account')

Jak zmienną przekazać do widoku

W tym momencie musimy lekko odbiec od tematu metod ustawienia kolejnych adresów url. Ponieważ warto wspomnieć w jaki sposób możemy zmienną z adresu url odczytać i przekazać do widoku.

def account(request, id):
     return render(request, 'home.html', {'user_id': id})

Jak wyżej zauważyłeś, przy ustawieniu adresu url podajemy typ zmiennej i jej nazwę. Nazwa zmiennej z adresu musi pokrywać się z nazwą zmiennej która wpada do funkcji.

Wyrażenia regularne jako wzór adresu url

W sytuacji gdy żaden z typów zmiennych w adresach url nam nie wystarcza. Przychodzi na ratunek możliwość wpisania wyrażenia regularnego.

Aby skorzystać z wyrażeń regularnych, funkcję „path” zmieniamy na „re_path„.

Wyrażenie regularne wpisujemy według wzoru poniżej:

(?P<nazwa_zmiennej>wyrażenie_regularne)

Przykład pełnego wzoru adresu url:

re_path(r'^user/(?P<id>[0-9]+)/$', views.account, name='account'),

Aby skorzystać z funkcji re_path musimy pamiętać o jej zaimportowaniu:

from django.urls import re_path

Pamiętaj również, że wszystkie zmienne z adresu url wpasowanego w wzór funkcji „re_path” będą ciągiem znaków „string„. Oznacza to, że nawet numer id z powyższego przykładu do widoku zostanie przekazany jako „string„. Gdybyśmy użyli funkcji „path” do widoku zmienna została by przekazana jako „int„.

Załadowanie zewnętrznych wzorów url

Django daje nam możliwość podzielenia wzorów url na osobne moduły. Wszystko co pisaliśmy powyżej możemy uznać za pojedynczy moduł. Przy dużej ilości adresów, może on przestać być czytelny. Poniżej podam przykład adresów wpisanych w jednym module:

path('company', views.companyList),
path('company/<str:name>', views.companyProfile),
path('company/add', views.companyAdd),
path('company/delete/<uuid:uuid>', views.companyDelete),
path('user', views.UserList),
path('user/<str:name>', views.userProfile),
path('user/add', views.userAdd),
path('user/delete/<uuid:uuid>', views.userDelete),

Nie wygląda to dobrze, na szczęście możemy zastosować tutaj metodę osobnego modułu, całość będzie się prezentowała następująco:

path('company', include('company.urls')),
path('user', include('user.urls')),

Dla przykładu warto podać zawartość pliku „company.urls„:

path('/', views.companyList),
path('/<int:id>', views.companyProfile),
path('/add', views.companyAdd),
path('/delete/<int:id>', views.companyDelete),

Analogicznie będzie wyglądał plik dla „user„. Pewnie zauważyłeś również, że w powyższym pliku nie powielamy już fragmentu „company” w adresie url, dodaje się on automatycznie.

Aby nie powielać przedrostka adresu „company„, możemy zastosować poniższą metodę:

urlpatterns = [
    path('company', include([
        path('/', views.companyList),
        path('/<int:id>', views.companyProfile),
        path('/add', views.companyAdd),
        path('/delete/<int:id>', views.companyDelete),
    ])),
]

Powyższy przykład umożliwia Tobie posegregowanie adresów, dzięki temu „urls” będzie znacznie czytelniejszy, a jednocześnie nie jesteś zmuszony do stosowania osobnych modułów.

Przekazanie dodatkowych danych do widoku

Przekazanie dodatkowych danych do funkcji w widoku jest możliwe dzięki wpisaniu kolejnego argumentu do funkcji „path” lub „re_path” w postaci listy.

path(r'^/user', views.user, {'nazwa': 'wartosc'}, name='user')

Teraz w widoku wystarczy zadeklarować kolejny parametr którego nazwa jest zgodna z nazwą powyższego przykładu:

def user(request, nazwa):

Niestandardowy konwerter zmiennych url

Ostatnią w tym wpisie omawianą funkcją w module „urls” jest tytułowy konwerter zmiennych w adresach url.

Możemy za pomocą konwertera zmienić każdą zmienną która jest w adresie url na zupełnie inną, dodać do niej jakąś wartość, przekonwertować jej typ, dosłownie wszystko.

Zainicjujmy zatem konwerter:

register_converter(converters.Example, 'name')

Przykładowy adres url:

path('/company/<str:name>', views.company, name='company'),

Plik konwertera (converters.py):

class Example:
    def to_python(self, value):
        return 'nazwa firmy:' + value

    def to_url(self, value):
        return value

Funkcja „to_python” poddaje modyfikacji wartość zmiennej „name” w celu późniejszego jej przekazania do widoku.

Funkcja „to_url” poddaje modyfikacji zawartość zmiennej „name” w celu zbudowania adresu url.

Powyższe metody mogą przykładowo zakodować informacje w „to_url” oraz zdekodować w „to_python” w celach bezpieczeństwa.

W moim przykładzie dodałem string „nazwa firmy:” do zmiennej w celu późniejszego przekazania jej do widoku, oraz nie poddałem żadnym modyfikacjom zmiennej w celu zbudowania linka na poziomie aplikacji.

Budowanie adresów url w django daje nam nieograniczone możliwości, zachęcam do eksperymentów. Jednocześnie pragnę zauważyć że mnogość możliwości jest po to aby nam życie ułatwić. Nie komplikujmy więc kodu dla zasady.

Wpis ten jest ściśle powiązany z dynamicznymi linkami.