URL-параметры и параметризированные запросы

Для удобства принято при выводе на экран разбивать объявления по рубрикам. Добавим на страницу панель навигации со списком рубрик. При выборе определенной рубрики на страницу будут выводится только объявления, которые к ней относятся.

Чтобы контроллер, отвечающий за вывод объявлений, мог смог их отфильтровать, ему необходимо передать ключ рубрики. Сделать это можно через GET-параметр, например, по такому шаблону: /bboard/?rubric=<ключ>.

Однако Django позволяет размещать параметр непосредственно в состав URL: bboard/<ключ>/ (URL-параметр).

В этом случае необходимо указать маршрутизатору, какая часть адреса является URL-параметром. Также указывается тип значения и имя параметра, которому будет присвоено извлеченное значение. Откроем urls.py приложения bboard и внесем правки:

. . .
from .vews import index, by_rubric
urlpatterns = [
    path('<int:rubric_id>', by_rubric),
    path('', index),
]

В набор маршрутов добавлена строка с путем <int:rubric_id>/. Угловые скобки помечают расположение URL=параметра, конструкция int указывает на тип параметра (целочисленный), rubric_id – имя параметра контроллера, который получит значение. Созданному маршруту будет сопоставлен контроллер-функция by_rubric (описан ниже).

При получении запроса с адресом http://localhost:8000/bboard/2/, выделит часть URL bboard/2/, далее удалит префикс bboard и определит, что полученный путь соответствует первому маршруту в списке. После этого будет запущен контроллер by_rubric, в качестве параметра ему будет передан ключ рубрики.

Маршруты, которые содержат URL-параметры, называют параметризированными.

Теперь необходимо открыть модуль views.py и дописать код контроллера-функции:

from .models import Rubric
def by_rubric(request, rubric_id):
    bbs = Bb.objects.filter(rubric=rubric_id)
    rubrics = Rubric.objects.all()
    current_rubric = Rubric.objects.get(pk=rubric_id)
    context = {'bbs': bbs, 'rubrics': rubrics,
  'current_rubrics': current_rubrics}
return render(request, 'bboard/by_rubric.html', context)

В объявлении функции был добавлен параметр rubric_id – ему будет присвоено содержимое URL-параметра, выделенное из интернет-адреса. В контекст шаблона добавлен список объявлений (фильтрация по внешнему ключу rubric), перечень всех доступных рубрик и текущую рубрику, чтобы вывести ее название.

В каталоге temptlates\bboard создадим шаблон by_rubric.html:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>{{ current_rubric.name }} :: Доска объявлений</title>
    </head>
    <body>
        <h1>Объявления</h1>
        <h2>Рубрика: {{ current_rubric.name }} </h2>
        <div>
            <a href="/bboard/">Главная</a>
            {% for rubric in rubrics %}
            <a href="/bboard/"{{ rubric.pk }}/">{{ rubric.name }}</a>
            {% endfor %}
        </div>
        {% for bb in bbs %}
        <div>
            <h2>{{ bb.title }}</h2>
            <p>{{ bb.content }}</p>
            <p>{{ bb.published|date:"d.m.Y H:i:s" }}</p>
        </div>
        {% endfor %}
   </body>
</html>

Обратите внимание, каким образом формируются интернет адреса отдельных рубрик.

Отредактируем шаблон bboard\index.html и контроллер index() таким образом, чтобы панель навигации также выводилась и на главной странице. Также сделаем так, чтобы рядом с каждым объявлением выводилось название его рубрики, выполненное в виде полноценной гиперссылки. Обновленный код контролера index():

def index(request):
    bbs = Bb.objects.all()
    rubrics = Rubric.objects.all()
    context = {'bbs': bbs, 'rubrics': rubrics}
    return render(request, 'bboard/index.html', context)

Код обновленного шаблона bboard\index.html с рубриками и панелью навигации:

<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <title>Главная :: Доска объявлений</title>
    </head>
    <body>
        <h1>Объявления</h1>
        <div>
            <a href="/bboard/">Главная</a>
           {% for rubric in rubrics %}
            <a href="/bboard/"{{ rubric.pk }}/">{{ rubric.name }}</a>
            {% endfor %}
        </div>
        {% for bb in bbs %}
        <div>
            <h2>{{ bb.title }}</h2>
            <p>{{ bb.content }}</p>
            <p><a href="/bboard/{{ bb.rubric.pk }}/">
            {{ bb.rubric.name }}</a></p>
            <p>{{ bb.published|date:"d.m.Y H:i:s" }}</p>
        </div>
        {% endfor %}
   </body>
</html>

После сохранения всех файлов и запуска отладочного веб-сервера проверим, как теперь отображается главная страница. Должна появиться панель навигации, расположенная сразу под заголовком, а также ссылки на рубрики. При переходе по такой ссылке откроется страница со списком соответствующих объявлений.





Добавить комментарий

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: