Для редактирование данных из админки создается наследник класса admin.ModelAdmin. Данный класс необходимо зарегистрировать и связать с моделью данных через вызов метода admin.site.register(<Класс модели данных>, <Класс админки>) или через декоратор @admin.register(<Класс модели данных>). Если в начале такого класса разместить комментарий в “”” Название страницы “”” – то это будет название для страницы редактирования.
При этом модель имеет ряд полей которые позволяют настроить ее поведение:
- list_editable – кортеж полей со списком имен доступных для редактирования. Только эти поля доступны для редактирования.
- save_on_top – (True/False) указывает выводить ли панель с действиями сверху формы.
- save_as_continue – (True/False) указывает выводить действие “сохранить и продолжить”.
- actions_on_bottom– (True/False) указывает выводить ли панель с действиями снизу формы (по молчанию установлено).
- save_as– (True/False) указывает отобразить действие для клонирование записи с изменением.
- empty_value_display – задает строку которая будет использоваться для пустых значений (по умолчанию черточка “-“).
- list_display_links – принимает кортеж со списком имен полей которые будут отображаться как ссылки для редактирования.
- list_filter – принимает кортеж со списком имен полей по которым необходимо создать фильтр, при этом если необходимо фильтровать по подчерненным поля, то имя поля указывается в формате <поле модели>__<имя поля подчерненной модели> (разделитель два символа подчеркивания. Еще одним вариантом может быть указание класса наследника admin.SimpleListFilter, для которого надо задать поля titile и parameter_name, а также реализовать методы lookup и queryset.
12345678910111213141516171819202122232425262728293031323334353637383940414243from datetime import datefrom django.contrib import adminfrom django.utils.translation import gettext_lazy as _class DecadeBornListFilter(admin.SimpleListFilter):# Human-readable title which will be displayed in the# right admin sidebar just above the filter options.title = _('decade born')# Parameter for the filter that will be used in the URL query.parameter_name = 'decade'def lookups(self, request, model_admin):"""Returns a list of tuples. The first element in eachtuple is the coded value for the option that willappear in the URL query. The second element is thehuman-readable name for the option that will appearin the right sidebar."""return (('80s', _('in the eighties')),('90s', _('in the nineties')),)def queryset(self, request, queryset):"""Returns the filtered queryset based on the valueprovided in the query string and retrievable via`self.value()`."""# Compare the requested value (either '80s' or '90s')# to decide how to filter the queryset.if self.value() == '80s':return queryset.filter(birthday__gte=date(1980, 1, 1),birthday__lte=date(1989, 12, 31))if self.value() == '90s':return queryset.filter(birthday__gte=date(1990, 1, 1),birthday__lte=date(1999, 12, 31))class PersonAdmin(admin.ModelAdmin):list_filter = (DecadeBornListFilter,)
Возможно указание специального шаблона через поле template.
12<span class="k">class</span> <span class="nc">FilterWithCustomTemplate</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">SimpleListFilter</span><span class="p">):</span><span class="n">template</span> <span class="o">=</span> <span class="s2">"custom_template.html"</span>
1234<span class="k">class</span> <span class="nc">PersonAdmin</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">ModelAdmin</span><span class="p">):</span><span class="n">list_filter</span> <span class="o">=</span> <span class="p">(</span><span class="p">(</span><span class="s1">'is_staff'</span><span class="p">,</span> <span class="n">admin</span><span class="o">.</span><span class="n">BooleanFieldListFilter</span><span class="p">),</span><span class="p">)</span>
1234<span class="k">class</span> <span class="nc">BookAdmin</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">ModelAdmin</span><span class="p">):</span><span class="n">list_filter</span> <span class="o">=</span> <span class="p">(</span><span class="p">(</span><span class="s1">'author'</span><span class="p">,</span> <span class="n">admin</span><span class="o">.</span><span class="n">RelatedOnlyFieldListFilter</span><span class="p">),</span><span class="p">)</span>
Фильтр в виде списка обычно появляются, только если у фильтра более одного выбора. Метод has_output () фильтра определяет, будет ли он отображаться. - search_fields – принимает кортеж со списком имен полей по которым необходимо организовать поиск, при этом если необходимо искать по подчерненным поля, то имя поля указывается в формате <поле модели>__<имя поля подчерненной модели> (разделитель два символа подчеркивания). При этом функция поиска также задается через два символа подчеркивания: first_name__exact, или перед именем поля поставить префикс:
Prefix Lookup ^ startswith
= iexact
@ search
None icontains
- readonly_fields – принимает кортеж со списком имен полей которые станут не доступными для редактирования, но будут отображаться.
- inlines – для связей типа ManyToMany и ForignKey указывается список классов наследников StackedInline (стэком) или TabularInline (таблицей), которые описывают форму редактирования множественных связей (для таких наследников есть поле extra, которое указывает сколько пустых записей должно отображаться при редактировании, по умолчанию 3).
- exclude – принимает кортеж со списком имен полей которые не должны отобразится (исключены из формы).
- fields – принимает кортеж со списком имен полей которые отобразятся. При этом если поле не указано здесь то его вообще не будет. А если какие то поля взять во вложенный кортеж то они будут сгруппированы (помещены в одну строку). Важное замечание, что если не заданы fields и fieldssets то отобразятся все доступные для редактирования поля формы (кроме автоматически генерируемых первичных ключей).
- fieldsets – (поведение аналогичное fields но более сложная структура описания) принимает кортеж состоящий из кортежей в котором первое поле имя группы или None, а второе значение словарь, в которым ключу “fields” предается кортеж со списком имен полей включенных в данную группу (если какие то поля указаны во вложенном кортеже, то они будут в одной строке), а ключ “classes” – задает кортеж классов которые будут связанны с группой (например ‘collapse’, свернет группу и добавит функционал по ее разворачиванию), а ключ “description” задает описание для группы (не отображаться для TabularInline). Важно понимать, что при задании этого поля видимыми останутся только поля которые им описаны все остальные будут не доступны. Например fieldsets=( (None, {“fields”: (“id”, (“name”, “year”))}), )
- filter_horizontal – принимает кортеж со списком имен полей. по умолчанию поле ManyToMany будет отображен как select с множественным выбором, но указание имени такого поля в этом кортеже создаст для него горизонтальный интерфейс с javascript для упрощенного поиска и выбора значений.
- filter_vertical – то же что filter_horizontal, но вертикальный интерфейс.
- list_per_page – указывает количество записей на страницу (по умолчанию 100)
- list_max_show_all – указывает при каком количестве записей в таблице будет появятся ссылка “показать все” (если записей больше этого значения то ссылки не будет).
- show_full_result_count – указывает выводит ли общее количество записей в таблице.
- autocomplete_fields – указывает кортеж со списком полей ForeignKey и/или ManyToManyField, для которых будет использоваться автозаполнение. При этом в ModelAdmin по которой будет идти поиск обязательно должно быть указан search_fields и пользователь обязан иметь права view или change.
- view_on_site – True/False создает ссылку для просмотра записи на сайте через вызов get_absolute_url.
- raw_id_fields – True/False заменяет раскрывающийся список выбора связанных записей на поле ввода со список ключей.
- sortable_by – указывает список полей по которым возможна сортировка. Указывается как список, кортеж или множество.
- paginator – класс который будет использован для формирование “пагинатора” по умолчанию это django.core.paginator.Paginator.
- prepopulated_fields – автоматически создать значение одного поля из значений других. Задается как словарь в котором ключ – это имя поля которое надо заполнить, а значение это кортеж со списком полей из которых надо взять значение. Сгенерированное значение создается путем объединения значений исходных полей, а затем путем преобразования этого результата в действительный слаг (например, замена черточек на пробелы; строчные буквы ASCII; и удаление различных английских стоп-слов, таких как ‘a’, ‘an’ , «как» и тому подобное).
Не принимает поля типов: ateTimeField, ForeignKey, OneToOneField, иManyToManyField. - preserve_filters – значение по умолчанию True и означает сохранение фильтров после создания/удаления/изменения записей.
- radio_fields – вместо selectbox использовать radio. Указывается как словарь с именем поля и значением admin.VERTICAL.
НЕ ВКЛЮЧАТЬ ЕСЛИ ПОЛЕ НЕ ForeignKey или choices. - ordering – список полей по которым производить сортировку, если не задан то сортировка берется с модели.
- list_select_related – управляет пакетным скачиванием значения для полей с отношениями. Значение может быть список, кортеж или бинарное значение (если значение True всегда будет вызываться функция select_related, значение False говорит, что функция будет вызвана только для полей ForeignKey), пустой список не вызывать функцию вообще, а список с именами полей только для этих полей .
- form – По умолчанию для ModelForm динамически форма. При этом она используется для создания формы, представленной на обеих страницах добавления / изменения. Вы можете легко предоставить свой собственный ModelForm для переопределения любого поведения формы по умолчанию на страницах добавления / изменения. Кроме того, вы можете настроить форму по умолчанию, а не указывать совершенно новую форму с помощью метода ModelAdmin.get_form ().
- list_display – принимает кортеж со списком имен полей которые необходимо отобразить. При этом в качестве значения можно указать функцию, которая будет принимать один параметр объект значения и будет возвращать строку как результат:
12345<span class="k">return</span> <span class="p">(</span><span class="s2">"</span><span class="si">%s</span> <span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">first_name</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">last_name</span><span class="p">))</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="n">upper_case_name</span><span class="o">.</span><span class="n">short_description</span> <span class="o">=</span> <span class="s1">'Name'</span><span class="k">class</span> <span class="nc">PersonAdmin</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">ModelAdmin</span><span class="p">):</span><span class="n">list_display</span> <span class="o">=</span> <span class="p">(</span><span class="n">upper_case_name</span><span class="p">,)</span>
123456<span class="k">class</span> <span class="nc">PersonAdmin</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">ModelAdmin</span><span class="p">):</span><span class="n">list_display</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'upper_case_name'</span><span class="p">,)</span><span class="k">def</span> <span class="nf">upper_case_name</span><span class="p">(</span><span class="bp">self</span><span class="p">,</span> <span class="n">obj</span><span class="p">):</span><span class="k">return</span> <span class="p">(</span><span class="s2">"</span><span class="si">%s</span> <span class="si">%s</span><span class="s2">"</span> <span class="o">%</span> <span class="p">(</span><span class="n">obj</span><span class="o">.</span><span class="n">first_name</span><span class="p">,</span> <span class="n">obj</span><span class="o">.</span><span class="n">last_name</span><span class="p">))</span><span class="o">.</span><span class="n">upper</span><span class="p">()</span><span class="n">upper_case_name</span><span class="o">.</span><span class="n">short_description</span> <span class="o">=</span> <span class="s1">'Name'</span>
123456789101112<span class="kn">from</span> <span class="nn">django.db</span> <span class="k">import</span> <span class="n">models</span><span class="k">class</span> <span class="nc">Person</span><span class="p">(</span><span class="n">models</span><span class="o">.</span><span class="n">Model</span><span class="p">):</span><span class="n">name</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">CharField</span><span class="p">(</span><span class="n">max_length</span><span class="o">=</span><span class="mi">50</span><span class="p">)</span><span class="n">birthday</span> <span class="o">=</span> <span class="n">models</span><span class="o">.</span><span class="n">DateField</span><span class="p">()</span><span class="k">def</span> <span class="nf">decade_born_in</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span><span class="k">return</span> <span class="bp">self</span><span class="o">.</span><span class="n">birthday</span><span class="o">.</span><span class="n">strftime</span><span class="p">(</span><span class="s1">'%Y'</span><span class="p">)[:</span><span class="mi">3</span><span class="p">]</span> <span class="o">+</span> <span class="s2">"0's"</span><span class="n">decade_born_in</span><span class="o">.</span><span class="n">short_description</span> <span class="o">=</span> <span class="s1">'Birth decade'</span><span class="k">class</span> <span class="nc">PersonAdmin</span><span class="p">(</span><span class="n">admin</span><span class="o">.</span><span class="n">ModelAdmin</span><span class="p">):</span><span class="n">list_display</span> <span class="o">=</span> <span class="p">(</span><span class="s1">'name'</span><span class="p">,</span> <span class="s1">'decade_born_in'</span><span class="p">)</span>
Поля ManyToManyField не принимаются так как требуют выполнения отдельных запросов (можно реализовать через свой метод)
Поля BooleanField – отображаться как “on” или “off” иконки
Все данный возвращаемые методами или функциями HTML экранируются. Для вставки html тегов применяется функциями format_html(). Методы и функции можно кастомизировать через атрибуты empty_value_display и short_description. Если метод возвращает бинарное значение то будет считаться что это бинарное значение. Атрибут admin_order_field будет указывать сортировку.
CSS в формате column-<field_name>.
ШАБЛОНЫ:
- ModelAdmin.add_form_template – путь к шаблону используемому add_view().
- ModelAdmin.change_form_template путь к шаблону используемому change_view().
- ModelAdmin.change_list_template путь к шаблону используемому changelist_view().
- ModelAdmin.delete_confirmation_template путь к шаблону используемому delete_view() для отображения страницы подтверждения удаления.
- ModelAdmin.delete_selected_confirmation_template путь к шаблону используемому delete_selected для отображения страницы подтверждения удаления.
- ModelAdmin.object_history_template путь к шаблону используемому history_view().
- ModelAdmin.popup_response_templateпуть к шаблону используемому response_add(), response_change(), и response_delete().
Больше информации:
https://docs.djangoproject.com/en/3.0/ref/contrib/admin/