Как изменить admin django

The web framework for perfectionists with deadlines.

Writing your first Django app, part 7¶

This tutorial begins where Tutorial 6 left off. We’re
continuing the web-poll application and will focus on customizing Django’s
automatically-generated admin site that we first explored in Tutorial 2.

Where to get help:

If you’re having trouble going through this tutorial, please head over to
the Getting Help section of the FAQ.

Customize the admin form¶

By registering the Question model with admin.site.register(Question),
Django was able to construct a default form representation. Often, you’ll want
to customize how the admin form looks and works. You’ll do this by telling
Django the options you want when you register the object.

Let’s see how this works by reordering the fields on the edit form. Replace
the admin.site.register(Question) line with:

polls/admin.py

from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fields = ['pub_date', 'question_text']

admin.site.register(Question, QuestionAdmin)

You’ll follow this pattern – create a model admin class, then pass it as the
second argument to admin.site.register() – any time you need to change the
admin options for a model.

This particular change above makes the “Publication date” come before the
“Question” field:

Fields have been reordered

This isn’t impressive with only two fields, but for admin forms with dozens
of fields, choosing an intuitive order is an important usability detail.

And speaking of forms with dozens of fields, you might want to split the form
up into fieldsets:

polls/admin.py

from django.contrib import admin

from .models import Question


class QuestionAdmin(admin.ModelAdmin):
    fieldsets = [
        (None,               {'fields': ['question_text']}),
        ('Date information', {'fields': ['pub_date']}),
    ]

admin.site.register(Question, QuestionAdmin)

The first element of each tuple in
fieldsets is the title of the fieldset.
Here’s what our form looks like now:

Form has fieldsets now

Customize the admin change list¶

Now that the Question admin page is looking good, let’s make some tweaks to the
“change list” page – the one that displays all the questions in the system.

Here’s what it looks like at this point:

Polls change list page

By default, Django displays the str() of each object. But sometimes it’d be
more helpful if we could display individual fields. To do that, use the
list_display admin option, which is a
tuple of field names to display, as columns, on the change list page for the
object:

polls/admin.py

class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date')

For good measure, let’s also include the was_published_recently() method
from Tutorial 2:

polls/admin.py

class QuestionAdmin(admin.ModelAdmin):
    # ...
    list_display = ('question_text', 'pub_date', 'was_published_recently')

Now the question change list page looks like this:

Polls change list page, updated

You can click on the column headers to sort by those values – except in the
case of the was_published_recently header, because sorting by the output
of an arbitrary method is not supported. Also note that the column header for
was_published_recently is, by default, the name of the method (with
underscores replaced with spaces), and that each line contains the string
representation of the output.

You can improve that by using the display()
decorator on that method (in polls/models.py), as follows:

polls/models.py

from django.contrib import admin

class Question(models.Model):
    # ...
    @admin.display(
        boolean=True,
        ordering='pub_date',
        description='Published recently?',
    )
    def was_published_recently(self):
        now = timezone.now()
        return now - datetime.timedelta(days=1) <= self.pub_date <= now

For more information on the properties configurable via the decorator, see
list_display.

Edit your polls/admin.py file again and add an improvement to the
Question change list page: filters using the
list_filter. Add the following line to
QuestionAdmin:

list_filter = ['pub_date']

That adds a “Filter” sidebar that lets people filter the change list by the
pub_date field:

Polls change list page, updated

The type of filter displayed depends on the type of field you’re filtering on.
Because pub_date is a DateTimeField, Django
knows to give appropriate filter options: “Any date”, “Today”, “Past 7 days”,
“This month”, “This year”.

This is shaping up well. Let’s add some search capability:

search_fields = ['question_text']

That adds a search box at the top of the change list. When somebody enters
search terms, Django will search the question_text field. You can use as many
fields as you’d like – although because it uses a LIKE query behind the
scenes, limiting the number of search fields to a reasonable number will make
it easier for your database to do the search.

Now’s also a good time to note that change lists give you free pagination. The
default is to display 100 items per page. Change list pagination, search boxes, filters, date-hierarchies, and
column-header-ordering
all work together like you think they should.

Customize the admin look and feel¶

Clearly, having “Django administration” at the top of each admin page is
ridiculous. It’s just placeholder text.

You can change it, though, using Django’s template system. The Django admin is
powered by Django itself, and its interfaces use Django’s own template system.

Customizing your project’s templates¶

Create a templates directory in your project directory (the one that
contains manage.py). Templates can live anywhere on your filesystem that
Django can access. (Django runs as whatever user your server runs.) However,
keeping your templates within the project is a good convention to follow.

Open your settings file (mysite/settings.py, remember) and add a
DIRS option in the TEMPLATES setting:

mysite/settings.py

TEMPLATES = [
    {
        'BACKEND': 'django.template.backends.django.DjangoTemplates',
        'DIRS': [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',
            ],
        },
    },
]

DIRS is a list of filesystem directories to check
when loading Django templates; it’s a search path.

Organizing templates

Just like the static files, we could have all our templates together, in
one big templates directory, and it would work perfectly well. However,
templates that belong to a particular application should be placed in that
application’s template directory (e.g. polls/templates) rather than the
project’s (templates). We’ll discuss in more detail in the
reusable apps tutorial why we do this.

Now create a directory called admin inside templates, and copy the
template admin/base_site.html from within the default Django admin
template directory in the source code of Django itself
(django/contrib/admin/templates) into that directory.

Where are the Django source files?

If you have difficulty finding where the Django source files are located
on your system, run the following command:

/

$ python -c "import django; print(django.__path__)"
...> py -c "import django; print(django.__path__)"

Then, edit the file and replace
{{ site_header|default:_('Django administration') }} (including the curly
braces) with your own site’s name as you see fit. You should end up with
a section of code like:

{% block branding %}
<h1 id="site-name"><a href="{% url 'admin:index' %}">Polls Administration</a></h1>
{% endblock %}

We use this approach to teach you how to override templates. In an actual
project, you would probably use
the django.contrib.admin.AdminSite.site_header attribute to more easily
make this particular customization.

This template file contains lots of text like {% block branding %}
and {{ title }}. The {% and {{ tags are part of Django’s
template language. When Django renders admin/base_site.html, this
template language will be evaluated to produce the final HTML page, just like
we saw in Tutorial 3.

Note that any of Django’s default admin templates can be overridden. To
override a template, do the same thing you did with base_site.html – copy
it from the default directory into your custom directory, and make changes.

Customizing your application’s templates¶

Astute readers will ask: But if DIRS was empty by
default, how was Django finding the default admin templates? The answer is
that, since APP_DIRS is set to True,
Django automatically looks for a templates/ subdirectory within each
application package, for use as a fallback (don’t forget that
django.contrib.admin is an application).

Our poll application is not very complex and doesn’t need custom admin
templates. But if it grew more sophisticated and required modification of
Django’s standard admin templates for some of its functionality, it would be
more sensible to modify the application’s templates, rather than those in the
project. That way, you could include the polls application in any new project
and be assured that it would find the custom templates it needed.

See the template loading documentation for more
information about how Django finds its templates.

Customize the admin index page¶

On a similar note, you might want to customize the look and feel of the Django
admin index page.

By default, it displays all the apps in INSTALLED_APPS that have been
registered with the admin application, in alphabetical order. You may want to
make significant changes to the layout. After all, the index is probably the
most important page of the admin, and it should be easy to use.

The template to customize is admin/index.html. (Do the same as with
admin/base_site.html in the previous section – copy it from the default
directory to your custom template directory). Edit the file, and you’ll see it
uses a template variable called app_list. That variable contains every
installed Django app. Instead of using that, you can hard-code links to
object-specific admin pages in whatever way you think is best.

Содержание

  • Предварительные условия
  • Настройка Django Admin
  • Кастомизация Django Admin
  • Изменение Change List с помощью list_display
  • Добавление ссылок на страницы других объектов
  • Добавление фильтров
  • Добавление поиска
  • Изменение способа редактирования моделей
  • Переопределение шаблонов Django Admin
  • Заключение

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

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

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

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

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

  • Get Started With Django Part 1: Build a Portfolio App
  • What is Pip? A Guide for New Pythonistas
  • Managing Multiple Python Versions With pyenv
  • What Virtual Environments Are Good For

Фрагменты кода в этом руководстве были протестированы на 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, ошеломляет. Вы можете глубже погрузиться в документацию, чтобы изучить такие темы, как встроенные формы, несколько сайтов администрирования, массовое редактирование, автозаполнение и многое другое. Удачного программирования!

Often the default Django admin page is great and it is all we need for our projects but sometimes we may want to expand what default admin interface can do. We have a lot of tools in Django to customize it to our own needs and in this article, we’ll learn how to customize the admin interface and add multiple features:

Let’s setup your project, add models into models.py and register your models.

models.py

Run following commands – 
 

Python manage.py makemigrations
Python manage.py migrate

Now we have created following models, Here is how they look like in Admin panel – 
 

Default Django admin

Django Admin – Redesign and Customization

Le’s check how we can add multiple features in Django admin panel. Here is a list of customizations – 
 

1. Changing order of Fields

By default, the admin will display fields in the detail view in the same order as defined in the model. But we can change that by making a few edits to the admin.py file without going to models.py and changing the order of different fields.

Movie model:
title
length
release_year
title=['release_year', 'title', 'length']
Movie_Model:
release_year
title
length

admin.py

Python

from django.contrib import admin

from .models import Movie, Customer

class MovieAdmin(admin.ModelAdmin):

    title = ['release_year', 'title', 'length']

admin.site.register(Movie, MovieAdmin)

admin.site.register(Customer)

Changed order of fields

2. Adding Search and Filters

Currently, we have only a few entries in our models, but what if the entries increase to hundreds or thousands due to more number of users? To get data of a particular entry will become tedious if we go by looking at each entry. Therefore we need to add a search bar or a filter feature to allow entries to be accessed easily.

Search by the following elements:
search_fields = ['title', 'length', 'release_year']
search_fields = ['first_name', 'last_name', 'phone']
Filter by the following elements:
list_filter = ['release_year']
list_filter = ['last_name']

app_folder / admin.py

Python

from django.contrib import admin

from .models import Movie, Customer

class MovieAdmin(admin.ModelAdmin):

    search_fields = ['title', 'length', 'release_year']

    list_filter = ['release_year']

class CustomerAdmin(admin.ModelAdmin):

    search_fields = ['first_name', 'last_name', 'phone']

    list_filter = ['last_name']

admin.site.register(Movie, MovieAdmin)

admin.site.register(Customer, CustomerAdmin)

Movies Model showing Filter and Search

Customers Model showing Search and Filter

3. Viewing Additional Fields

In admin interface, normally we see only one field of our models in the list view. We can add more fields to view with list_display.

list_display=['title', 'release_year']
list_display=['first_name', 'last_name', 'phone']

admin.py

Python

from django.contrib import admin

from .models import Movie, Customer

class MovieAdmin(admin.ModelAdmin):

  list_display =['title', 'release_year']

class customerAdmin(admin.ModelAdmin):

  list_display =['first_name', 'last_name', 'phone']

admin.site.register(Movie, MovieAdmin)

admin.site.register(Customer, CustomerAdmin)

title and release year Fields in Movie Model

first name, last name and phone number Fields  in Customer Model

4. Editing List View

You can add the ability to edit attribute values directly from the list view instead of going to the detail view

editable_list = ['phone']

admin.py

Python

from django.contrib import admin

from .models import Movie, Customer

class CustomerAdmin(admin.ModelAdmin):

    editable_list = ['phone']

admin.site.register(Movie)

admin.site.register(Customer, CustomerAdmin)

Phone Number is editable here in Customer Class

5. Admin Template

Sometimes you may want to change the layout and user interface of admin interface for which you need to add your own templates into the project which will then be reflected to your django admin interface.

Create a folder templates in the root folder and inside it, create another folder admin. Now add your html file inside the admin folder.

templates—->admin—->base_site.html

HTML

{% extends "admin/base.html" %}

{% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}

{% block branding %}

<h1 id="site-name" style="font-family: cursive;" ><a href="{% url 'admin:index' %}">Video Rental Administration</a></h1>

{% endblock %}

{% block nav-global %}{% endblock %}

Heading is changed 

Here, the heading in the admin interface has changed due to the addition of html file. Sometimes template doesn’t get applied to the interface, to avoid that, make sure you’ve done correct template configuration in the settings.py file.

import os

TEMPLATES=[

'DIRS': [os.path.join(BASE_DIR, 'templates')],

]

This how you can customize the admin template in Django as per your requirements.

Often the default Django admin page is great and it is all we need for our projects but sometimes we may want to expand what default admin interface can do. We have a lot of tools in Django to customize it to our own needs and in this article, we’ll learn how to customize the admin interface and add multiple features:

Let’s setup your project, add models into models.py and register your models.

models.py

Run following commands – 
 

Python manage.py makemigrations
Python manage.py migrate

Now we have created following models, Here is how they look like in Admin panel – 
 

Default Django admin

Django Admin – Redesign and Customization

Le’s check how we can add multiple features in Django admin panel. Here is a list of customizations – 
 

1. Changing order of Fields

By default, the admin will display fields in the detail view in the same order as defined in the model. But we can change that by making a few edits to the admin.py file without going to models.py and changing the order of different fields.

Movie model:
title
length
release_year
title=['release_year', 'title', 'length']
Movie_Model:
release_year
title
length

admin.py

Python

from django.contrib import admin

from .models import Movie, Customer

class MovieAdmin(admin.ModelAdmin):

    title = ['release_year', 'title', 'length']

admin.site.register(Movie, MovieAdmin)

admin.site.register(Customer)

Changed order of fields

2. Adding Search and Filters

Currently, we have only a few entries in our models, but what if the entries increase to hundreds or thousands due to more number of users? To get data of a particular entry will become tedious if we go by looking at each entry. Therefore we need to add a search bar or a filter feature to allow entries to be accessed easily.

Search by the following elements:
search_fields = ['title', 'length', 'release_year']
search_fields = ['first_name', 'last_name', 'phone']
Filter by the following elements:
list_filter = ['release_year']
list_filter = ['last_name']

app_folder / admin.py

Python

from django.contrib import admin

from .models import Movie, Customer

class MovieAdmin(admin.ModelAdmin):

    search_fields = ['title', 'length', 'release_year']

    list_filter = ['release_year']

class CustomerAdmin(admin.ModelAdmin):

    search_fields = ['first_name', 'last_name', 'phone']

    list_filter = ['last_name']

admin.site.register(Movie, MovieAdmin)

admin.site.register(Customer, CustomerAdmin)

Movies Model showing Filter and Search

Customers Model showing Search and Filter

3. Viewing Additional Fields

In admin interface, normally we see only one field of our models in the list view. We can add more fields to view with list_display.

list_display=['title', 'release_year']
list_display=['first_name', 'last_name', 'phone']

admin.py

Python

from django.contrib import admin

from .models import Movie, Customer

class MovieAdmin(admin.ModelAdmin):

  list_display =['title', 'release_year']

class customerAdmin(admin.ModelAdmin):

  list_display =['first_name', 'last_name', 'phone']

admin.site.register(Movie, MovieAdmin)

admin.site.register(Customer, CustomerAdmin)

title and release year Fields in Movie Model

first name, last name and phone number Fields  in Customer Model

4. Editing List View

You can add the ability to edit attribute values directly from the list view instead of going to the detail view

editable_list = ['phone']

admin.py

Python

from django.contrib import admin

from .models import Movie, Customer

class CustomerAdmin(admin.ModelAdmin):

    editable_list = ['phone']

admin.site.register(Movie)

admin.site.register(Customer, CustomerAdmin)

Phone Number is editable here in Customer Class

5. Admin Template

Sometimes you may want to change the layout and user interface of admin interface for which you need to add your own templates into the project which will then be reflected to your django admin interface.

Create a folder templates in the root folder and inside it, create another folder admin. Now add your html file inside the admin folder.

templates—->admin—->base_site.html

HTML

{% extends "admin/base.html" %}

{% block title %}{% if subtitle %}{{ subtitle }} | {% endif %}{{ title }} | {{ site_title|default:_('Django site admin') }}{% endblock %}

{% block branding %}

<h1 id="site-name" style="font-family: cursive;" ><a href="{% url 'admin:index' %}">Video Rental Administration</a></h1>

{% endblock %}

{% block nav-global %}{% endblock %}

Heading is changed 

Here, the heading in the admin interface has changed due to the addition of html file. Sometimes template doesn’t get applied to the interface, to avoid that, make sure you’ve done correct template configuration in the settings.py file.

import os

TEMPLATES=[

'DIRS': [os.path.join(BASE_DIR, 'templates')],

]

This how you can customize the admin template in Django as per your requirements.

Понравилась статья? Поделить с друзьями:
  • Как изменить checksum
  • Как изменить bios date
  • Как изменить caps lock на обычный шрифт
  • Как изменить bin файл прошивки
  • Как изменить caps lock на другую клавишу