# Административная панель и параметрические ссылки --- ## Административная панель ---- Административный веб-сайт предоставляет доступ ко всем моделям, объявленным во всех приложениях проекта. Мы можем просматривать, добавлять, править и удалять записи, фильтровать и сортировать их. ---- Стандартное приложение `django.contrib.auth` использует для хранения списков зарегистрированных пользователей, групп и их привилегий особые модели. Для них в базе данных должны быть созданы таблицы, и создание этих таблиц выполняют особые миграции. ---- Остановим отладочный веб-сервер и отдадим в командной строке команду: `python manage.py createsuperuser` ---- Утилита `manage.py` запросит у нас имя создаваемого суперпользователя, его адрес электронной почты и пароль, который потребуется ввести дважды: ``` Username (leave blank to use 'vlad'): admin Email address: admin@somesite.ru Password: Password (again): ``` ---- После этого русифицируем проект Django. Откроем модуль `settings.py` пакета конфигурации и найдем в нем вот такое выражение: `LANGUAGE_CODE = 'en-us'` ---- Исправим это выражение, занеся в него код русского языка: `LANGUAGE_CODE = 'ru'` ---- Запустим отладочный веб-сервер и войдем на административный сайт, перейдя по интернет-адресу http://localhost:8000/admin/. Будет выведена страница входа с формой, в которой нужно набрать имя и пароль, введенные при создании суперпользователя, и нажать кнопку `Войти`. ---- Откроем модуль административных настроек admin.py пакета приложения bboard и заменим имеющийся в нем небольшой код. ``` from django.contrib import admin from .models import Bb admin.site.register(Bb) ``` ---- Мы вызвали метод `register()` у экземпляра класса `Adminsite`, представляющего сам административный сайт и хранящегося в переменной `site` модуля `django.contrib.admin.` Этому методу мы передали в качестве параметра ссылку на класс нашей модели Bb. ---- Откроем модуль models.py пакета приложения bboard и исправим код класса модели Bb: ``` class Bb (models.Model): title = models.CharField(max_length=50, verbose_name='Товар') content = models.TextField(null=True, blank=True, verbose_name='Описание') price = models.FloatField(null=True, blank=True, verbose_name='Цена') published = models.DateTimeField(auto_now_add=True, db_index=True, verbose_name='Опубликовано') class Meta: verbose_name_plural = 'Объявления' verbose_name = 'Объявление' ordering = ['-published'] ``` ---- В классе модели мы объявили вложенный класс Meta, а в нем — атрибуты класса, которые зададут параметры уже самой модели: * verbose_name_plural — название модели во множественном числе; * verbose_name — название модели в единственном числе. * ordering — последовательность полей, по которым по умолчанию будет выполняться сортировка записей. ---- Теперь мы можем исправить код контроллера `index()`, убрав из выражения, извлекающего список записей, указание сортировки: ``` def index(request): bbs = Bb.objects.all() ``` ---- Редактор объявляется в модуле административных настроек admin.py пакета приложения. Откроем его и заменим имеющийся в нем код на: ``` from django.contrib import admin from .models import Bb class BbAdmin(admin.ModelAdmin): list_display = ('title', 'content', 'price', 'published') list_display_links = ('title', 'content') search_fields = ('title', 'content', ) admin.site.register (Bb, BbAdmin) ``` ---- Мы использовали следующие атрибуты класса: * list_display— последовательность имен полей, которые должны выводиться в списке записей; * list_dispiay_links— последовательность имен полей, которые должны быть преобразованы в гиперссылки, ведущие на страницу правки записи; * search_fields— последовательность имен полей, по которым должна выполняться фильтрация. ---- Объявим класс модели Rubric, которая будет представлять рубрики объявлений, дописав в модуль models.py пакета приложения bboard следующий код. ``` class Rubric (models.Model): name = models.CharField (max_length=20, db_index=True, verbose_name='Название') class Meta: verbose_name_plural = 'Рубрики' verbose_name = 'Рубрика' ordering = ['name'] ``` ---- Создадим во вторичной модели такое поле, назвав его rubric: ``` class Bb(models.Model): rubric = models.ForeignKey('Rubric', null=True, on_delete=models.PROTECT, verbose_name='Рубрика') class Meta: ``` ---- Класс `ForeignKey` представляет поле внешнего ключа, в котором фактически будет храниться ключ записи из первичной модели. Первым параметром конструктору этого класса передается строка с именем класса первичной модели, поскольку вторичная модель у нас объявлена раньше первичной. ---- Сохраним исправленный модуль и сгенерируем миграции, которые внесут необходимые изменения в базу данных: `python manage.py makemigrations bboard` ---- Выполним созданную миграцию: `python manage.py migrate` ---- Сразу же зарегистрируем новую модель на административном сайте, добавив в модуль `admin.py` пакета приложения два выражения: ``` from .models import Rubric admin.site.register(Rubric) ``` ---- Откроем модуль models.py, если уже закрыли его, и добавим в объявление класса модели Rubric вот этот код: ``` class Rubric (models.Model) : def __str__(self): return self.name class Meta: ``` ---- Осталось сделать так, чтобы в списке записей модели Bb, помимо всего прочего, выводились рубрики объявлений. Для чего достаточно добавить в последовательность имен полей, присвоенную атрибуту `list display` класса `BbAdmin`, поле `rubric`: ``` class BbAdmin (admin. Model Admin): list_display = ('title', 'content', 'price', 'published', 'rubric') ``` --- ## Параметрические ссылки ---- Откроем модуль urls.py пакета приложения bboard и внесем в него такие правки (добавленный код выделен полужирным шрифтом): ``` from .views import index, by_rubric urlpatterns = [ path ('<int: rubric_id>/', by_rubric) , path('', index), ] ``` ---- Откроем модуль views.py и добавим в него код контроллера-функции by_rubric() ``` 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_rubric': current_rubric} return render(request, 'bboard/by_rubric.html', context) ``` ---- Создадим в папке templates\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/'>Главная</а> {% 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> ``` ---- Исправим контроллер index о и шаблон bboard\index.html таким образом, чтобы на главной странице нашего сайта выводилась та же самая панель навигации. ``` 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>0бъявления</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> ``` ---- Посмотрим на HTML-код гиперссылок, указывающих на страницы рубрик: ``` <а href=”/bboard/{{ rubric.pk }}/”>{{ rubric.name }}</a> ``` ---- Сначала нужно дать маршрутам имена, создав тем самым именованные маршруты. Откроем модуль urls.py пакета приложения и исправим код, создающий набор маршрутов, следующим образом: ``` urlpatterns = [ path('<int:rubric_id>/', by_rubric, name='by_rubric'), path ('', index, name='index'), ] ``` ---- Откроем шаблон bboard\index.html, найдем в нем фрагмент кода: `<а href="/bboard/{{ rubric.pk }}/">` и заменим его на: `<a href="{% url 'by_rubric' rubric.pk %}">` ---- Имя маршрута указывается первым параметром тега url, а значения URL-napa- метров — последующими. Найдем код, создающий гиперссылку на главную страницу: `<а href='/bboard/'>` Заменим его на: `<a href="{% url 'index' %}">` --- Задачи: * Создать титульную страницу с переходом к списку обьявлений (единственное условие - выводит два самых свежих обьявления). * Создать таблицу продавцов (обязательные поля - имя, номер телефона, остальное по усмотрению), привязать её таблице обьявлений * Создать фильтрацию по продавцу * Создать форму, которая будет производить запись в базу данных (повышенная сложность)
{"metaMigratedAt":"2023-06-16T11:39:09.447Z","metaMigratedFrom":"Content","title":"Административная панель и параметрические ссылки","breaks":true,"contributors":"[{\"id\":\"0d39d5a3-691d-488c-8f1e-1a0fb0be4f13\",\"add\":11301,\"del\":1789}]"}
    257 views