Кастомизация админ-панели Django

Содержание

Фреймворк Django поставляется с мощным инструментом администрирования под названием admin. Вы можете использовать его прямо из коробки, чтобы быстро добавлять, удалять или редактировать любую модель базы данных из веб-интерфейса. А можете, написав немного кода, самостоятельно настроить Django admin и вывести свои административные возможности на новый уровень.

В этом руководстве вы узнаете, как:

  • Добавить столбцы атрибутов в список объектов модели.
  • Добавить ссылки на страницы других объектов.
  • Добавить фильтры в список объектов модели.
  • Добавить поиск в список объектов модели.
  • Изменить форму редактирования объекта.
  • Переопределить шаблоны Django admin.

Предварительные условия

Чтобы получить максимум от этого руководства, вы должны быть знакомы с Django, особенно с моделями. Поскольку Django не является частью стандартной библиотеки Python, то вы также должны быть знакомы с pip и pyenv (или аналогичным инструментом виртуального окружения). Чтобы узнать больше об этих темах, можете ознакомиться со следующими ресурсами:

Фрагменты кода в этом руководстве были протестированы на Django 3.0.7. Они должны работать в любой версии, которую вы используете, но могут быть незначительные различия.


Настройка Django Admin

Django admin предоставляет веб-интерфейс для создания и управления объектами модели базы данных. Чтобы увидеть его в действии, вам сначала понадобится проект Django и несколько моделей. Установите Django в чистое виртуальное окружение:

$ python -m pip install django
$ django-admin startproject School
$ cd School
$ ./manage.py startapp core
$ ./manage.py migrate
$ ./manage.py createsuperuser
Username: admin
Email address: admin@example.com
Password:
Password (again):

Сначала создайте новый проект Django под названием School с приложением под названием core. Затем выполните команду migrate и создайте администратора. Доступ к админ-панели  Django разрешен только пользователям с флагами staff или superuser, поэтому для создания суперпользователя используется команда createsuperuser.

Вам также необходимо внести изменения в файл School/settings.py, чтобы включить новое приложение с именем core:

# School/settings.py
# ...

INSTALLED_APPS = [
    "django.contrib.admin",
    "django.contrib.auth",
    "django.contrib.contenttypes",
    "django.contrib.sessions",
    "django.contrib.messages",
    "django.contrib.staticfiles",
    "core",    # Add this line
]

Каталог приложения core будет содержать следующие файлы:

core/
│
├── migrations/
│   └── __init__.py
│
├── __init__.py
├── admin.py
├── apps.py
├── models.py
├── tests.py
└── views.py

Из этих файлов нас интересуют два:

  1. models.py, в котором определяются модели.
  2. admin.py,  в котором модели регистрируются в Django admin.

Чтобы продемонстрировать кастомизацию Django admin, вам понадобятся несколько моделей. Отредактируйте core/models.py следующим образом:

from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models

class Person(models.Model):
    last_name = models.TextField()
    first_name = models.TextField()
    courses = models.ManyToManyField("Course", blank=True)

    class Meta:
        verbose_name_plural = "People"

class Course(models.Model):
    name = models.TextField()
    year = models.IntegerField()

    class Meta:
        unique_together = ("name", "year", )

class Grade(models.Model):
    person = models.ForeignKey(Person, on_delete=models.CASCADE)
    grade = models.PositiveSmallIntegerField(
        validators=[MinValueValidator(0), MaxValueValidator(100)])
    course = models.ForeignKey(Course, on_delete=models.CASCADE)

Эти модели представляют учащихся, проходящих курсы в школе. У модели Course есть два поля: название курса и год, в котором он был начат. Модель Person имеет три поля: имя и фамилия учащегося и курсы, которые он проходит (ноль или более). Grade содержит оценку, полученную учащимся (Person) на курсе (Course).

Вот диаграмма, показывающая отношения между объектами:

Имена таблиц в базе данных немного отличаются от этих, но они связаны с моделями, показанными выше.

Каждую модель, которую вы хотите отображать в админ-панели Django, необходимо зарегистрировать. Делается это в файле admin.py. Модели из core/models.py регистрируются в соответствующем файле core/admin.py:

from django.contrib import admin

from core.models import Person, Course, Grade

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    pass

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    pass

@admin.register(Grade)
class GradeAdmin(admin.ModelAdmin):
    pass

Вы почти готовы к работе. После выполнения миграции вы можете запустить сервер разработки Django и увидеть следующие результаты:

$ ./manage.py makemigrations
$ ./manage.py migrate
Operations to perform:
  Apply all migrations: admin, auth, contenttypes, core, sessions
Running migrations:
  Applying contenttypes.0001_initial... OK
  Applying auth.0001_initial... OK
  Applying admin.0001_initial... OK
  ...
  Applying core.0001_initial... OK
  Applying core.0002_auto_20200609_2120... OK
  Applying sessions.0001_initial... OK
$ ./manage.py runserver
Watching for file changes with StatReloader
Performing system checks...

System check identified no issues (0 silenced).
Django version 3.0.7, using settings 'School.settings'
Starting development server at http://127.0.0.1:8000/
Quit the server with CONTROL-C.

Теперь перейдите по адресу http://127.0.0.1:8000/admin, чтобы увидеть интерфейс администратора. Вам будет предложено войти в систему. Используйте учетные данные, созданные с помощью команды createsuperuser.

На главной странице Django admin перечислены все зарегистрированные модели:

django admin

Теперь вы можете использовать админ-панель для создания объектов в своей базе данных. Щелкнув по названию модели, вы увидите список всех объектов в базе данных для этой модели. Вот, например, список людей (Person):

django admin

Сначала список пустой, как и ваша база данных. Нажав ADD PERSON, вы можете создать человека в базе данных. После сохранения вы вернетесь к списку объектов Person:

django admin

Хорошая новость в том, что у вас есть объект. Плохая новость в том, что Person object (1) сообщает вам id объекта и ничего больше. По умолчанию, Django admin отображает каждый объект, вызывая функцию str(). Вы можете сделать эту страницу более полезной, добавив метод .__str__() в класс Person в core/models.py:

class Person(models.Model):
    last_name = models.TextField()
    first_name = models.TextField()
    courses = models.ManyToManyField("Course", blank=True)

    def __str__(self):
        return f"{self.last_name}, {self.first_name}"

Добавление метода Person.__str__() изменяет отображение: теперь вместо id отображаются имя и фамилия человека. Вы можете обновить страницу, чтобы увидеть изменения:

django admin

Так-то лучше! Теперь вы можете увидеть некоторую информацию об объекте Person. Рекомендуется добавить подобные методы как к объектам Course, так и к объектам Grade:

class Course(models.Model):
    # ...

    def __str__(self):
        return f"{self.name}, {self.year}"

class Grade(models.Model):
    # ...

    def __str__(self):
        return f"{self.grade}, {self.person}, {self.course}"

Чтобы увидеть полный эффект от вашей кастомизации, вам нужно иметь некоторые данные в своей базе данных. Вы можете создать свои собственные данные прямо сейчас, или можете пропустить этот шаг и использовать фикстуры (fixture).

Django позволяет загружать данные в базу данных и выгружать из нее с помощью файлов, называемых фикстурами. Скопируйте следующее в файл с именем core/fixtures/school.json:

[
    {
        "model": "core.person",
        "pk": 1,
        "fields": {
            "last_name": "Harris",
            "first_name": "Xander",
            "courses": [
                1,
                3
            ]
        }
    },
    {
        "model": "core.person",
        "pk": 3,
        "fields": {
            "last_name": "Rosenberg",
            "first_name": "Willow",
            "courses": [
                1,
                2,
                3
            ]
        }
    },
    {
        "model": "core.person",
        "pk": 16,
        "fields": {
            "last_name": "Summers",
            "first_name": "Buffy",
            "courses": [
                1,
                2,
                3
            ]
        }
    },
    {
        "model": "core.course",
        "pk": 1,
        "fields": {
            "name": "CompSci G11",
            "year": 1998
        }
    },
    {
        "model": "core.course",
        "pk": 2,
        "fields": {
            "name": "Psych 101",
            "year": 1999
        }
    },
    {
        "model": "core.course",
        "pk": 3,
        "fields": {
            "name": "Library Science G10",
            "year": 1997
        }
    },
    {
        "model": "core.grade",
        "pk": 1,
        "fields": {
            "person": 16,
            "grade": 68,
            "course": 1
        }
    },
    {
        "model": "core.grade",
        "pk": 2,
        "fields": {
            "person": 16,
            "grade": 87,
            "course": 2
        }
    },
    {
        "model": "core.grade",
        "pk": 3,
        "fields": {
            "person": 16,
            "grade": 76,
            "course": 3
        }
    },
    {
        "model": "core.grade",
        "pk": 4,
        "fields": {
            "person": 1,
            "grade": 58,
            "course": 1
        }
    },
    {
        "model": "core.grade",
        "pk": 5,
        "fields": {
            "person": 1,
            "grade": 58,
            "course": 3
        }
    },
    {
        "model": "core.grade",
        "pk": 6,
        "fields": {
            "person": 3,
            "grade": 98,
            "course": 3
        }
    },
    {
        "model": "core.grade",
        "pk": 7,
        "fields": {
            "person": 3,
            "grade": 97,
            "course": 2
        }
    }
]

Создав файл, вы можете использовать команду loaddata, чтобы загрузить его в свою базу данных:

$ ./manage.py loaddata school
Installed 13 object(s) from 1 fixture(s)

Теперь в вашей базе данных есть несколько объектов Person, Course и Grade.

А сейчас, когда у вас есть некоторые данные для работы, вы готовы приступить к кастомизации админ-панели Django.


Кастомизация Django Admin

Умные люди, создавшие фреймворк Django, не только создали админку, но и сделали это таким образом, чтобы вы могли кастомизировать ее для своих проектов. Когда вы ранее регистрировали объект PersonAdmin, он наследовался от admin.ModelAdmin. Большая часть настроек, которые вы можете сделать с помощью Django admin, выполняется путем модификации класса ModelAdmin, и вы, конечно, можете изменять его!

ModelAdmin имеет более тридцати атрибутов и почти пятьдесят методов. Вы можете использовать каждый из них для настройки админ-панели и управления интерфейсами ваших объектов. Каждый из этих вариантов подробно описан в документации.

В довершение ко всему, админка построена с использованием шаблонов Django. Механизм шаблонов Django позволяет вам переопределять существующие шаблоны, а поскольку Django admin — это просто еще один набор шаблонов, это означает, что вы можете полностью изменить его HTML-код.

Хотя это выходит за рамки данного руководства, вы даже можете создать несколько сайтов администрирования. Это может показаться излишним, но это позволяет вам фантазировать и делать разные сайты для пользователей с разными разрешениями.

Django admin разделен на три основные области:

  1. App index
  2. Change lists
  3. Change forms

В app index перечислены ваши зарегистрированные модели. Change list автоматически создается для каждой зарегистрированной модели и содержит список объектов для этой модели. Когда вы добавляете или редактируете один из этих объектов, вы делаете это с помощью change form.

В предыдущем примере app index отображал объекты Person, Course и Grade. При нажатии на People отображаются change list’ы для объектов Person. На странице change list, щелкнув по объекту Buffy Summers, вы попадете на страницу change form, чтобы отредактировать данные о Buffy Summers.


Изменение Change List с помощью list_display

Реализация метода .__str__() — это быстрый способ изменить представление объекта Person с бессмысленной строки на понятные данные. Поскольку это представление также будет отображаться в раскрывающихся списках со множественным выбором, вы определенно захотите сделать его максимально простым и понятным.

Вы можете кастомизировать страницу change list гораздо большим количеством способов, чем просто изменить строковое представление объекта. Атрибут list_display объекта admin.ModelAdmin указывает, какие столбцы будут отображаться в change list’e. Это значение представляет собой кортеж атрибутов моделируемого объекта. Например, в core/admin.py измените PersonAdmin следующим образом:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    list_display = ("last_name", "first_name")

Приведенный выше код модифицирует ваш Person change list таким образом, что теперь будут отображаться атрибуты last_name и first_name для каждого объекта Person. Каждый атрибут отображается в столбце на странице:

Эти два столбца кликабельны, что позволяет сортировать страницу по данным столбца. Django admin также учитывает атрибут ordering в Meta-классе:

class Person(models.Model):
    # ...

    class Meta:
        ordering = ("last_name", "first_name")

    # ...

Добавление атрибута ordering приведет к тому, что по умолчанию все запросы к Person будут упорядочены по last_name, а затем по first_name. Django будет соблюдать этот порядок по умолчанию как в админке, так и при получении объектов.

Кортеж list_display может ссылаться на любой атрибут объекта. Он также может ссылаться на метод в самом admin.ModelAdmin. Снова изменим PersonAdmin:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    list_display = ("last_name", "first_name", "show_average")

    def show_average(self, obj):
        from django.db.models import Avg
        result = Grade.objects.filter(person=obj).aggregate(Avg("grade"))
        return result["grade__avg"]

В приведенном выше коде вы добавляете столбец, в котором будет отображаться средний бал каждого учащегося. show_average() вызывается один раз для каждого объекта, отображаемого в списке.

Параметр obj — это объект для отображаемой строки. В этом случае вы используете его для запроса соответствующих объектов Grade для учащегося, затем получаете среднее значение Grade.grade. Вы можете увидеть результаты здесь:

Имейте в виду, что средний бал на самом деле нужно рассчитывать в объекте модели Person. Скорее всего, вам понадобятся данные, находящиеся где-нибудь еще, а не только в Django admin. Если бы у вас был такой метод, вы могли бы добавить его в атрибут list_display. Приведенный пример показывает, что вы можете делать в объекте ModelAdmin, но, вероятно, это не лучший выбор для вашего кода.

По умолчанию сортируются только те столбцы, которые являются атрибутами объекта. show_average() — нет. Это связано с тем, что сортировка выполняется с помощью QuerySet. В некоторых случаях есть способы сортировки этих столбцов, но это выходит за рамки нашего руководства.

Заголовок столбца основан на имени метода. Вы можете изменить заголовок, добавив атрибут к методу:

def show_average(self, obj):
    result = Grade.objects.filter(person=obj).aggregate(Avg("grade"))
    return result["grade__avg"]

show_average.short_description = "Average Grade"

По умолчанию Django защищает вас от HTML в строках, если строка является результатом пользовательского ввода.  Чтобы отображение включало HTML, вы должны использовать format_html():

def show_average(self, obj):
    from django.utils.html import format_html

    result = Grade.objects.filter(person=obj).aggregate(Avg("grade"))
    return format_html("<b><i>{}</i></b>", result["grade__avg"])

show_average.short_description = "Average"

Теперь столбец show_average() имеет кастомное название «Average» и выделен курсивом:

К сожалению, в Django еще не добавлена поддержка f-строк для format_html(), поэтому используется синтаксис str.format().


Добавление ссылок на страницы других объектов

Объекты довольно часто ссылаются на другие объекты с помощью внешних ключей (foreign key). Вы можете указать в list_display метод, возвращающий ссылку HTML. Внутри core/admin.py измените класс CourseAdmin следующим образом:

from django.urls import reverse
from django.utils.http import urlencode

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    list_display = ("name", "year", "view_students_link")

    def view_students_link(self, obj):
        count = obj.person_set.count()
        url = (
            reverse("admin:core_person_changelist")
            + "?"
            + urlencode({"courses__id": f"{obj.id}"})
        )
        return format_html('<a href="{}">{} Students</a>', url, count)

    view_students_link.short_description = "Students"

Теперь Course change list состоит из трех столбцов:

  1. название курса.
  2. год, в котором был начат курс.
  3. ссылка, отображающая количество учащихся, проходящих курс.

Вы можете увидеть результат на следующем скриншоте:

Когда вы нажимаете по ссылке 2 Students, вы попадаете на страницу Person change list с примененным фильтром. На отфильтрованной странице показаны только ученики из Psych 101: Buffy и Willow. Xander не поступил в университет.

В примере кода для поиска URL-адреса в админке используется функция reverse(). Вы можете найти любую страницу Django admin, используя следующее соглашение об именах:

"admin:%(app)s_%(model)s_%(page)"

Эта структура имени разбивается следующим образом:

  • admin: — это пространство имен.
  • app — это название приложения.
  • model — это объект модели.
  • page — это тип страницы Django admin.

В приведенном выше примере view_students_link() вы используете admin:core_person_changelist, чтобы получить ссылку на страницу change list объекта Person в приложении core.

Вот доступные URL-адреса:

Страница

URL

Цель

Change list

%(app)s\_%(model)s\_changelist

Список страниц объектов модели

Add

%(app)s\_%(model)s\_add

Страница создания объекта

History

%(app)s\_%(model)s\_history

Страница истории изменений объекта

Принимает object_id в качестве параметра

Delete

%(app)s\_%(model)s\_delete

Страница удаления объекта

Принимает object_id в качестве параметра

Change

%(app)s\_%(model)s\_change

Страница редактирования объекта

Принимает object_id в качестве параметра

Вы можете отфильтровать страницу change list, добавив к URL-адресу строку запроса. Эта строка запроса изменяет QuerySet, используемый для заполнения страницы. В приведенном выше примере строка запроса "?courses__id={obj.id}" фильтрует список Person по id курса (отображаются только те объекты, которые имеют соответствующее значение Person.course).

Эти фильтры поддерживают поиск полей QuerySet с использованием двойного подчеркивания (__). Вы можете получить доступ к атрибутам связанных объектов, а также использовать модификаторы фильтра, такие как __exact и __startswith.

Полную информацию о том, чего вы можете достичь с помощью атрибута list_display, вы можете найти в документации Django admin.


Добавление фильтров

Помимо фильтрации данных в change list через URL-адрес, вы также можете фильтровать с помощью встроенного виджета. Добавьте атрибут list_filter к объекту CourseAdmin в core/admin.py:

@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
    list_display = ("name", "year", "view_students_link")
    list_filter = ("year", )
# ...

list_filter отобразит новый раздел на странице со списком ссылок. В этом случае ссылки фильтруют страницу по годам. Список фильтров автоматически заполняется значениями лет, используемыми объектами Course в базе данных:

Если щелкнуть по году справа, в список будут включены только объекты курса с этим значением года. Вы также можете фильтровать по атрибутам связанных объектов, используя синтаксис поиска поля __. Например, вы можете отфильтровать объекты GradeAdmin по course__year, показывая объекты Grade только для курсов определенного года.

Если вам нужен больший контроль над фильтрацией, вы даже можете создать объекты фильтра, которые определяют атрибуты поиска и соответствующий QuerySet.


Добавление поиска

Фильтры — не единственный способ уменьшить объем данных на экране. Django admin также поддерживает поиск с помощью опции search_fields, которая добавляет на экран поле поиска. Вы устанавливаете его с помощью кортежа, содержащего имена полей, которые будут использоваться для построения поискового запроса в базе данных.

Все, что пользователь вводит в поле поиска, используется в условии OR полей, фильтрующих QuerySet. По умолчанию каждый параметр поиска окружен знаками %. То есть, если вы ищете r, то в результатах появится любое слово с r внутри. Вы можете быть более точными, указав модификатор __ в поле поиска.

Отредактируйте PersonAdmin в core/admin.py следующим образом:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    search_fields = ("last_name__startswith", )

В приведенном выше коде поиск основан на фамилии. Модификатор __startswith ограничивает поиск фамилиями, которые начинаются с параметра поиска. Поиск по R дает следующие результаты:

Каждый раз, когда выполняется поиск на странице change list, Django admin вызывает метод get_search_results() вашего объекта admin.ModelAdmin. Он возвращает QuerySet с результатами поиска. Вы можете точно настроить поиск, перегрузив метод и изменив QuerySet. Более подробную информацию можно найти в документации.


Изменение способа редактирования моделей

Вы можете кастомизировать не только страницу change list. Страницы, используемые для добавления или изменения объекта, основаны на ModelForm. Django автоматически генерирует форму на основе редактируемой модели.

Вы можете контролировать, какие поля включены, а также их порядок. Измените свой объект PersonAdmin, добавив атрибут fields:

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    fields = ("first_name", "last_name", "courses")
# ...

Страницы добавления и изменения для Person теперь помещают атрибут first_name перед атрибутом last_name, хотя сама модель указывает обратное:

ModelAdmin.get_form() отвечает за создание ModelForm для вашего объекта. Вы можете переопределить этот метод, чтобы изменить форму. Добавьте в PersonAdmin следующий метод:

def get_form(self, request, obj=None, **kwargs):
    form = super().get_form(request, obj, **kwargs)
    form.base_fields["first_name"].label = "First Name (Humans only!):"
    return form

Теперь, когда отображается страница добавления или изменения, метка поля first_name будет изменена.

Изменения метки может быть недостаточно, чтобы помешать вампирам зарегистрироваться в качестве студентов. Если вам не нравится ModelForm, созданная для вас Django admin, вы можете использовать атрибут form для регистрации пользовательской формы. Внесите следующие дополнения и изменения в core/admin.py:

from django import forms

class PersonAdminForm(forms.ModelForm):
    class Meta:
        model = Person
        fields = "__all__"

    def clean_first_name(self):
        if self.cleaned_data["first_name"] == "Spike":
            raise forms.ValidationError("No Vampires")

        return self.cleaned_data["first_name"]

@admin.register(Person)
class PersonAdmin(admin.ModelAdmin):
    form = PersonAdminForm
# ...

Приведенный выше код обеспечивает дополнительную проверку на страницах добавления и изменения человека (Person). Объекты ModelForm имеют богатый механизм проверки. В этом случае поле first_name проверяется на соответствие имени «Spike». ValidationError не позволяет студентам с этим именем зарегистрироваться:

Изменяя или заменяя объект ModelForm, вы можете полностью контролировать внешний вид и проверку страниц, которые вы используете для добавления или изменения объекта.


Переопределение шаблонов Django Admin

Разработчики Django реализовали админку с помощью механизма шаблонов Django. Это сделало их работу немного проще, но это также принесет вам пользу, позволив вам переопределить шаблоны. Вы можете полностью кастомизировать админку, изменив шаблоны, используемые для отображения страниц.

Вы можете увидеть все шаблоны, используемые в админке, заглянув в пакет Django в своем виртуальном окружении:

.../site-packages/django/contrib/admin/templates/
│
├── admin/
│   │
│   ├── auth/
│   │   └── user/
│   │       ├── add_form.html
│   │       └── change_password.html
│   │
│   ├── edit_inline/
│   │   ├── stacked.html
│   │   └── tabular.html
│   │
│   ├── includes/
│   │   ├── fieldset.html
│   │   └── object_delete_summary.html
│   │
│   ├── widgets/
│   │   ├── clearable_file_input.html
│   │   ├── foreign_key_raw_id.html
│   │   ├── many_to_many_raw_id.html
│   │   ├── radio.html
│   │   ├── related_widget_wrapper.html
│   │   ├── split_datetime.html
│   │   └── url.html
│   │
│   ├── 404.html
│   ├── 500.html
│   ├── actions.html
│   ├── app_index.html
│   ├── base.html
│   ├── base_site.html
│   ├── change_form.html
│   ├── change_form_object_tools.html
│   ├── change_list.html
│   ├── change_list_object_tools.html
│   ├── change_list_results.html
│   ├── date_hierarchy.html
│   ├── delete_confirmation.html
│   ├── delete_selected_confirmation.html
│   ├── filter.html
│   ├── index.html
│   ├── invalid_setup.html
│   ├── login.html
│   ├── object_history.html
│   ├── pagination.html
│   ├── popup_response.html
│   ├── prepopulated_fields_js.html
│   ├── search_form.html
│   └── submit_line.html
│
└── registration/
    ├── logged_out.html
    ├── password_change_done.html
    ├── password_change_form.html
    ├── password_reset_complete.html
    ├── password_reset_confirm.html
    ├── password_reset_done.html
    ├── password_reset_email.html
    └── password_reset_form.html

У шаблонизатора Django есть определенный порядок загрузки шаблонов. При загрузке шаблона он использует первый шаблон, соответствующий названию. Вы можете переопределить шаблоны админ-панели, используя ту же структуру каталогов и имена файлов.

Шаблоны Django admin находятся в двух каталогах:

  1. admin — предназначен для страниц объекта модели.
  2. registration — предназначен для смены пароля, входа и выхода.

Чтобы кастомизировать страницу выхода, вам необходимо переопределить правильный файл. Относительный путь, ведущий к файлу, должен совпадать с тем, который был переопределен. Нас интересует файл registration/logged_out.html. Начнем с создания каталога в проекте School:

$ mkdir -p templates/registration

Теперь сообщите Django о вашем новом каталоге шаблонов в файле School/settings.py. Найдите TEMPLATES и добавьте папку в список DIR:

# School/settings.py
# ...

TEMPLATES = [
    {
        "BACKEND": "django.template.backends.django.DjangoTemplates",

        # Добавление папки
        "DIRS": [os.path.join(BASE_DIR, "templates"), ],
        "APP_DIRS": True,
        "OPTIONS": {
            "context_processors": [
                "django.template.context_processors.debug",
                "django.template.context_processors.request",
                "django.contrib.auth.context_processors.auth",
                "django.contrib.messages.context_processors.messages",
            ],
        },
    },
]

Шаблонизатор ищет каталоги в параметре DIR перед каталогами приложений, поэтому вместо этого будет загружено все, что имеет то же имя, что и шаблон админ-панели. Чтобы увидеть это в действии, скопируйте файл logged_out.html в каталог templates/registration, затем измените его:

{% extends "admin/base_site.html" %}
{% load i18n %}

{% block breadcrumbs %}<div class="breadcrumbs"><a href="{% url 'admin:index' %}">{% trans 'Home' %}</a></div>{% endblock %}

{% block content %}

<p>You are now leaving Sunnydale</p>

<p><a href="{% url 'admin:index' %}">{% trans 'Log in again' %}</a></p>

{% endblock %}

Вы кастомизировали страницу выхода. Если вы нажмете LOG OUT, то увидите кастомное сообщение:

Шаблоны Django admin отличаются глубокой вложенностью и не очень интуитивно понятны, но вы можете полностью контролировать их представление, если вам это нужно. Некоторые пакеты, включая Grappelli и Django Admin Bootstrap, полностью заменили шаблоны Django admin, изменив их внешний вид.

Django Admin Bootstrap еще не совместим с Django 3, а Grappelli только недавно добавил поддержку, так что у него все еще могут быть некоторые проблемы. Но если вы хотите увидеть силу переопределения шаблонов админки, ознакомьтесь с этими проектами!


Заключение

Django admin — это мощный встроенный инструмент, дающий вам возможность создавать, обновлять и удалять объекты в вашей базе данных с помощью веб-интерфейса. Вы можете настроить Django admin для выполнения практически всего, что захотите.

В этом руководстве вы узнали, как:

  • Зарегистрировать свои модели в Django admin.
  • Добавить атрибуты в виде столбцов в change list.
  • Создать значения столбцов с вычисляемым содержимым.
  • Сделать перекрестные ссылки на страницы админки.
  • Фильтровать страницы change list.
  • Добавлять поиск на страницы change list.
  • Кастомизировать объект ModelForm.
  • Изменять HTML в шаблонах Django admin.

Это руководство охватывает только некоторые аспекты. Количество настроек, которые вы можете кастомизировать в Django admin, ошеломляет. Вы можете глубже погрузиться в документацию, чтобы изучить такие темы, как встроенные формы, несколько сайтов администрирования, массовое редактирование, автозаполнение и многое другое. Удачного программирования!