# Административная панель и параметрические ссылки
---
## Административная панель
----
Административный веб-сайт предоставляет доступ ко всем моделям, объявленным во всех приложениях проекта. Мы можем просматривать, добавлять, править и удалять записи, фильтровать и сортировать их.
----
Стандартное приложение `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}]"}