Курс по Django: https://stepik.org/a/183363
Архив проекта: 06_sitewomen.zip
Сейчас в
нашем проекте маршруты приложения women подключаются с
помощью функции include:
urlpatterns = [
path('admin/', admin.site.urls),
path('', include('women.urls')),
]
Соответственно, за
главную страницу отвечает функция представления index, а за вывод
разделов – функция categories. Но у нас может быть множество категорий и
хотелось бы, например, их отображать с помощью таких URL:
127.0.0.1:8000/cats/1/
127.0.0.1:8000/cats/2/
127.0.0.1:8000/cats/3/
...
Как прописать
такой URL-шаблон в Django? Для этого в
списке адресов приложения следует указать числовой параметр. Это можно сделать
следующим образом (в файле women/urls.py):
urlpatterns = [
path('', views.index),
path('cats/<int:cat_id>/', views.categories),
]
Смотрите, здесь
в угловых скобках записан параметр cat_id, который имеет
тип int – целочисленный.
Этот тип в маршрутах называется конвертером. И указанный путь будет
соответствовать любым комбинациям URL с фрагментом ‘cats/число/’. Далее,
в функции представления categories мы уже можем использовать этот
параметр:
def categories(request, cat_id):
return HttpResponse(f"<h1>Статьи по категориям</h1><p >id:{cat_id}</p>")
Как видите, все
предельно просто. Помимо конвертера int в Django можно
использовать и другие:
- str – любая не
пустая строка, исключая символ ‘/’;
- int – любое
положительное целое число, включая 0;
- slug – слаг, то
есть, латиница ASCII таблицы, цифры, символы дефиса и
подчеркивания;
- uuid – цифры, малые
латинские символы ASCII, дефис;
- path – любая не
пустая строка, включая символ ‘/’.
https://docs.djangoproject.com/en/4.2/topics/http/urls/
Например, мы
можем добавить еще один маршрут для доступа к категориям через слаг (slug) следующим
образом:
path('cats/<slug:cat_slug>/', views.categories_by_slug),
Изменим функцию представления:
def categories_by_slug(request, cat_slug):
return HttpResponse(f"<h1>Статьи по категориям</h1><p >slug:{ cat_slug }</p>")
И теперь в
качестве категории можно указывать не только числа, но и строки в виде слага,
например, так:
127.0.0.1:8000/cats/3/
127.0.0.1:8000/cats/sport/
127.0.0.1:8000/cats/music/
Как видите,
слаги понятнее для пользователя и поисковых систем. Сайты с такими URL, в среднем,
лучше индексируются и занимают более высокие позиции в поисковой выдаче.
Причем, когда передается число, то отрабатывает первый маршрут из URL с числовым
конвертером, если же числовой шаблон не подходит, то проверяется следующий со
слагом. И здесь очень важен порядок. Если поменять и записать сначала конвертер
со слагом, а затем, с числом:
urlpatterns = [
path('', views.index),
path('cats/<slug:cat_slug>/', views.categories_by_slug),
path('cats/<int:cat_id>/', views.categories),
]
то всегда будет
срабатывать слаг, так как число – это частный случай слага. На это обращайте
внимание: сначала следует прописывать частные конвертеры, а затем, все более
общие.
Если по каким-то
причинам представленных типов для URL недостаточно, то в Django имеется функция
re_path()
которая делает
все то же самое, но с использованием регулярных выражений. Например, определим URL, в котором
можно указывать год в виде четырех чисел:
re_path(r'^archive/(?P<year>[0-9]{4})/', views.archive),
Здесь year – это имя
переменной, которая будет содержать введенный год.
Добавим функцию представления
archive:
def archive(request, year):
return HttpResponse(f"<h1>Архив по годам</h1><p >{year}</p>")
И теперь мы
можем обращаться к этому URL, указывая ровно 4 цифры:
http://127.0.0.1:8000/archive/2020/
Если же указать
меньше или больше чисел, то шаблон URL не совпадет и возникнет
исключение 404 – страница не найдена. Вот так, достаточно гибко можно задавать
список URL для механизма
маршрутизации в Django.
Создание собственных конвертеров
Фреймворк Django позволяет
создавать свои собственные конвертеры, используемые при анализе URL-адресов.
Например, вместо того чтобы использовать функцию re_path() с регулярным
выражением, мы можем создать конвертер, который бы выделял и проверял год в URL-адресе. Подробная
документация приведена на следующей странице:
https://docs.djangoproject.com/en/4.2/topics/http/urls/
В частности, в разделе
«Registering custom path converters» приведен пример
класса FourDigitYearConverter с регулярным
выражением для выделения четырех цифр:
class FourDigitYearConverter:
regex = "[0-9]{4}"
def to_python(self, value):
return int(value)
def to_url(self, value):
return "%04d" % value
Кроме того, у
него имеются два метода:
- to_python() –
для преобразования фрагмента URL в требуемый тип данных;
- to_url() – для
преобразования параметра в формат, требуемый для представления в URL.
В частности, в
классе FourDigitYearConverter в методе to_python() параметр value преобразуется в
целое число (год), а в методе to_url() обратно в
строку из четырех цифр.
Нам вполне
подходит этот класс, поэтому я его просто скопирую и добавлю в приложение women в файл converters.py. Затем,
перейдем в файл urls.py приложения women и
зарегистрируем этот конвертер с именем year4 для
использования в URL-шаблонах:
register_converter(converters.FourDigitYearConverter, "year4")
Далее, в
коллекции urlpatterns вместо функции re_path() можно
прописать:
path('archive/<year4:year>/', views.archive),
При этом
параметр year будет
автоматически преобразован в целое число благодаря методу to_python() класса FourDigitYearConverter. В этом легко
убедиться, поставив точку останова в функции представления archive() и запустив
Django в режиме
отладки.
Курс по Django: https://stepik.org/a/183363