Custom Django admin interface.
Project description
paper-admin
Custom Django admin interface based on Bootstrap 4.
Requirements
- Python >= 3.6
- Django >= 2.2
Installation
Add paper_admin
to your INSTALLED_APPS setting before django.contrib.admin
.
INSTALLED_APPS = [
"paper_admin",
"paper_admin.patches.dal", # optional
"paper_admin.patches.django_solo", # optional
"paper_admin.patches.mptt", # optional
"paper_admin.patches.logentry_admin", # optional
"paper_admin.patches.post_office", # optional
"paper_admin.patches.tree_queries", # optional
# ...
"django.contrib.admin",
# ...
]
Patches
Некоторые сторонние библиотеки переопределяют стандартные
шаблоны Django и в рамках интерфейса paper_admin
выглядят инородно. Поэтому приходится применять патчи.
В состав paper_admin
включены следующие патчи:
-
paper_admin.patches.dal
Исправляет стили виджетов django-autocomplete-light -
paper_admin.patches.django_solo
Исправляет хлебные крошки в django-solo. -
paper_admin.patches.mptt
Адаптация django-mptt. Добавляет возможность сортировки узлов дерева (при указании свойстваsortable
). -
paper_admin.patches.logentry_admin
Исправление фильтров и скрытие ненужных кнопок в django-logentry-admin. -
paper_admin.patches.post_office
Исправление виджета списка email адресов в django-post_office -
paper_admin.patches.tree_queries
Добавление возможности сортировки узлов дерева для django-tree-queries.Необходимо использовать специальный класс вместо
ModelAdmin
:# admin.py from django.contrib import admin from paper_admin.patches.tree_queries.admin import TreeNodeModelAdmin # <-- from .models import MyTreeNode @admin.register(MyTreeNode) class MyTreeNodeAdmin(TreeNodeModelAdmin): ... sortable = "position"
Note: как правило, патчи должны быть указаны в INSTALLED_APPS
до библиотек,
которые они исправляют.
Сортировка объектов при помощи Drag & Drop
Для того, чтобы экземпляры модели можно было сортировать в интерфейсе администратора, необходимо выполнить два условия.
-
Добавить в модель числовое поле, которое будет хранить порядковый номер.
from django.db import models class MyModel(models.Model): position = models.IntegerField( "position", default=0, editable=False # опционально )
-
Указать название поля в свойстве
sortable
.from django.contrib import admin class MyModelAdmin(admin.ModelAdmin): sortable = "position" # ...
Результат:
https://user-images.githubusercontent.com/6928240/125331456-0f1bb280-e359-11eb-8b17-b04be4b1e62c.mp4
Сохранение сортировки происходит через AJAX-запрос.
Таким же путём можно включить сортировку инлайн-форм, но в этом случае сортировка происходит с помощью кнопок и сохраняется вместе со всей страницей при нажатии кнопки "Save":
from django.contrib import admin
class TablularInline(admin.TabularInline):
sortable = "position"
# ...
Результат:
https://user-images.githubusercontent.com/6928240/125331956-b6004e80-e359-11eb-8422-832dfe37bb6c.mp4
Сортировка paper-admin
совместима с django-mptt.
Менять местами можно только те элементы, которые имеют общего родителя и находятся на одном уровне
вложенности:
https://user-images.githubusercontent.com/6928240/125340277-55760f00-e363-11eb-94d4-49a978cb7ae4.mp4
Вкладки
Форму добавления/редактирования объекта можно разделить на вкладки.
Список вкладок указывается в атрибуте tabs
:
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
class TablularInlines(admin.TabularInline):
# имя вкладки, на которой должен быть отображен формсет
tab = 'common-tab'
@admin.register(Page)
class PageAdmin(admin.ModelAdmin):
fieldsets = (
(_('First Section'), {
'tab': 'common-tab',
'fields': (
# ...
),
}),
(_('Second Section'), {
'tab': 'common-tab',
'fields': (
# ...
)
}),
(_('Links'), {
'tab': 'links-tab',
'fields': (
# ...
)
}),
)
tabs = [
('common-tab', _('General')),
('links-tab', _('Links')),
('inlines-tab', _('Inlines')),
]
inlines = (TablularInlines, )
Результат:
https://user-images.githubusercontent.com/6928240/125336032-4e003700-e35e-11eb-8399-9cff90ea7aca.mp4
Вкладки можно добавлять динамически, с помощью метода get_tabs
:
from django.contrib import admin
@admin.register(Page)
class PageAdmin(admin.ModelAdmin):
def get_tabs(self, request, obj=None):
return [
# ...
]
Стилизация
Стилизация fieldset
Django даёт возможность указать произвольные CSS-классы и описание для любого fieldset.
paper-admin
предоставляет набор готовых CSS-классов для стилизации fieldset:
paper-card--primary
paper-card--secondary
paper-card--info
paper-card--danger
paper-card--success
paper-card--warning
from django.contrib import admin
from django.utils.translation import gettext_lazy as _
@admin.register(Page)
class PageAdmin(admin.ModelAdmin):
fieldsets = (
(_('Info Section'), {
'classes': ('paper-card--info', ),
'description': _('Description for the fieldset'),
'fields': (
# ...
),
}),
(_("Success Section"), {
"classes": ("paper-card--success",),
"fields": (
# ...
)
}),
(_("Danger Section"), {
"classes": ("paper-card--danger",),
"fields": (
# ...
)
}),
)
Результат:
Стилизация рядов таблицы
Для каждого ряда таблицы вызывается метод get_row_classes
, который должен вернуть
список CSS-классов, которые будут добавлены к тэгу <tr>
.
from django.contrib import admin
@admin.register(Page)
class PageAdmin(admin.ModelAdmin):
def get_row_classes(self, request, obj=None):
if obj.name.startswith("M"):
return ["table-success"]
elif obj.name.startswith("P"):
return ["table-info"]
return []
Результат:
Стилизация inline-форм
Inline-формам тоже можно назначить произвольные CSS-классы с помощью метода
get_form_classes
:
from django.contrib import admin
class StackedInline(admin.StackedInline):
def get_form_classes(self, request, obj):
if obj.name.startswith("P"):
return ["paper-card--success"]
elif obj.name.startswith("M"):
return ["paper-card--info"]
return []
class TablularInlines(admin.TabularInline):
def get_form_classes(self, request, obj):
if obj.name.startswith("P"):
return ["table-success"]
elif obj.name.startswith("M"):
return ["table-info"]
return []
Результат:
Меню
Меню в сайдбаре настраивается путем заполнения списка PAPER_MENU
в settings.py
.
PAPER_MENU = [
dict( # Пункт меню для главной страницы
label=_("Dashboard"),
url="admin:index",
icon="fa fa-fw fa-lg fa-area-chart",
),
dict( # Пункт меню для приложения
app="app",
icon="fa fa-fw fa-lg fa-home",
models=[
"Tag",
"Category",
"SubCategory",
]
),
"-", # Разделитель
"auth", # Приложение
"sites", # Приложение
]
Пункт меню может быть задан одним из четырех способов:
- Имя приложения (app_label).
Все модели выбранного приложения образуют подменю. Порядок моделей будет определен автоматически. - Путь к модели (app_label.model_name).
Создаст пункт меню с заголовком, соответствующим названию модели и соответствующим URL. - Строка-разделитель ("-")
Добавляет горизонтальную линию. С помощью разделителей можно визуально группировать пункты меню. - Словарь.
Самый гибкий способ создания пункта меню. В словаре можно явным образом указать название пункта меню, его URL, иконку, CSS-классы и вложенные пункты.
При использовании словаря можно указать следующие ключи:
label
:str
- заголовок пункта менюurl
:str
- URL или имя URL-шаблона (напримерapp:index
)icon
:str
- CSS-классы иконкиclasses
:str
- CSS-классы пункта менюperms
:str/list/callable
- права, необходимые для отображения пункта. Для определения суперюзера и сотрудников, можно использовать специальные значенияsuperuser
иstaff
.app
:str
- имя приложения. Неявно добавляется к именам моделей вmodels
.models
:list/dict
- дочерние пункты меню. Может содержать имена моделей или пункты меню.
Пример 1.
from django.urls import reverse_lazy
PAPER_MENU = [
dict(
app="app",
icon="fa fa-fw fa-lg fa-home",
models=[
dict(
label=_("Index"),
url=reverse_lazy("admin:app_list", kwargs={
"app_label": "app"
})
), # Произвольный пункт меню
"Tag", # Модель app.Tag
"Category", # Модель app.Category
]
),
"-", # Разделитель
"auth", # Приложение
]
Пример 2. Проверка прав.
Этот пункт меню увидят только сотрудники, имеющие право на изменение модели Tag
.
На доступность страниц параметр perms
никак не влияет. Если пользователь знает
адрес страницы или ссылка на неё имеется где-то ещё, то пользователь сможет на неё
перейти.
PAPER_MENU = [
dict(
app="app",
perms=["staff", "app.change_tag"],
models=[
"Tag",
]
)
]
Бейдж (badge)
Полоса с текстом в сайдбаре.
Её основное предназначение - визуально обозначить окружение, в котором работает административный интерфейс. Так вы не перепутаете сервер разработки с продашеном.
Цвет полосы и текст устанавливаются в settings.py
:
PAPER_ENVIRONMENT_NAME = "development"
PAPER_ENVIRONMENT_COLOR = "#FFFF00"
Settings
PAPER_FAVICON
Путь к favicon-файлу, который будет использоваться в интерфейсе админимтратора.
Default: "paper_admin/dist/assets/default_favicon.png"
PAPER_ENVIRONMENT_NAME
Текст на бейжде в сайдбаре.
Default: ""
PAPER_ENVIRONMENT_COLOR
Цвет фона бейджа.
Default: ""
PAPER_MENU
Меню.
Default: None
PAPER_MENU_DIVIDER
При встрече указанной строки в списке пунктов PAPER_MENU
,
на её место будут вставлен горизонтальный разделитель.
Default: "-"
PAPER_MENU_PERM_STAFF
Ключевое слово в параметре perms
пункта меню PAPER_MENU
,
которое указывает, что текущий пункт меню должен быть показан
только при условии, что у пользователя установлен флаг is_staff
.
Default: "staff"
PAPER_MENU_PERM_SUPERUSER
Ключевое слово в параметре perms
пункта меню PAPER_MENU
,
которое указывает, что текущий пункт меню должен быть показан
только при условии, что у пользователя установлен флаг is_superuser
.
Default: "superuser"
PAPER_MENU_HIDE_SINGLE_CHILD
Если родительский пункт меню содержит единственный дочерний пункт,
то вместо отображения выпадающего списка, родительский пункт будет вести
на страницу дочернего пункта.
Default: True
PAPER_DEFAULT_TAB_NAME
Алиас вкладки по-умолчанию для форм админки.
Default: "general"
PAPER_DEFAULT_TAB_TITLE
Заголовок вкладки по-умолчанию для форм админки.
Default: _("General")
PAPER_LOCALE_PACKAGES
Список модулей, из которых должны загружаться переводы
для JavaScriptCatalog
интерфейса администратора.
Default: ["paper_admin", "django.contrib.admin"]
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Hashes for paper_admin-3.1.0-py2.py3-none-any.whl
Algorithm | Hash digest | |
---|---|---|
SHA256 | ecc4806b92e22de4d936a272cc321c538ecfdacab2c4fe2ab17e92efb057ad92 |
|
MD5 | 25e48601b949d81d2cd027817cc83ebc |
|
BLAKE2b-256 | 1dba20324615f54cad87cf960c9905daa719b4e6d8f008894a99797a79e6fd39 |