mod: админка (14) для Лейблов LabelAdminForm и LabelAdmin добавлен кастомный save_model (вывод после добавления/изменения записи) и универсальная хелпер-функция.
This commit is contained in:
@@ -10,7 +10,7 @@ from .models import (
|
||||
TbImage, TbArticle, TbArtist, TbItem, TbLabel, TbSeller,
|
||||
TbOffer, TbSource, TbOfferHistory, TbMusicStyle
|
||||
)
|
||||
from .utils import validate_entity_for_admin_form
|
||||
from .utils import validate_entity_for_admin_form, generate_admin_save_message
|
||||
|
||||
|
||||
# ============================================================================
|
||||
@@ -353,6 +353,7 @@ class MusicStyleAdmin(admin.ModelAdmin):
|
||||
list_display_links = ('id', 's_style_name',)
|
||||
search_fields = ('s_style_name', 'j_style_synonyms',)
|
||||
readonly_fields = ('t_style_created', 't_style_updated',)
|
||||
|
||||
fieldsets = (
|
||||
('Основные данные о музыкальном стиле', {
|
||||
'fields': ('s_style_name', 'j_style_synonyms',),
|
||||
@@ -542,6 +543,30 @@ class LabelAdmin(RequestInFormMixin, admin.ModelAdmin):
|
||||
list_display_links = ('id', 's_label',)
|
||||
search_fields = ('s_label',)
|
||||
readonly_fields = ('t_label_created', 't_label_updated')
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
"""
|
||||
Переопределяем save_model для добавления информативных сообщений в админку.
|
||||
|
||||
Максимально поджарый код - все сложности с получением старого значения
|
||||
и определением типа операции делает хелпер generate_admin_save_message().
|
||||
"""
|
||||
# Стандартное сохранение записи через Django
|
||||
# (в т.ч. автоматическое создание связанной статьи в методе save модели TbLabel)
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
# Генерируем и отправляем информативное сообщение об сохранении
|
||||
# Хелпер сам:
|
||||
# - определяет тип операции (create vs update)
|
||||
# - формирует нужное сообщение (success vs warning)
|
||||
generate_admin_save_message(
|
||||
request=request,
|
||||
obj=obj,
|
||||
is_new=not change, # Django: change=False для новых, True для существующих
|
||||
related_article=obj.k_label_to_article,
|
||||
obj_field_name='s_label',
|
||||
)
|
||||
|
||||
fieldsets = (
|
||||
('Основные данные о лейбле/издателе', {
|
||||
'fields': ('s_label', 'j_label_metadata',),
|
||||
|
||||
@@ -12,6 +12,7 @@ from django.core.exceptions import ValidationError
|
||||
from django.db.models import QuerySet
|
||||
from django.db.models.expressions import RawSQL
|
||||
from django.utils.html import mark_safe
|
||||
from django.contrib import messages
|
||||
from lpon_site.settings import (
|
||||
SLUG_MAX_LENGTH, KEY_SYNONYM,
|
||||
VALIDATE_KEY__MATCH_TYPE, VALIDATE_KEY__MODEL, VALIDATE_KEY__VALUE,
|
||||
@@ -1222,3 +1223,113 @@ def update_synonyms_in_metadata(
|
||||
# иначе Django может не сохранить изменения
|
||||
setattr(instance, metadata_field_name, metadata_dict)
|
||||
|
||||
|
||||
def generate_admin_save_message(request, obj, is_new, related_article,
|
||||
obj_field_name='s_label',
|
||||
article_title_field='s_article_title'):
|
||||
"""
|
||||
Генерирует и отправляет информативное сообщение об сохранении объекта в админке.
|
||||
|
||||
Функция анализирует тип операции (создание/редактирование/переименование) и
|
||||
отправляет соответствующее сообщение с ссылкой на связанную статью.
|
||||
|
||||
Использует Django messages framework для отправки (success/warning в зависимости от ситуации).
|
||||
Ссылка на статью открывается в новой вкладке для удобства админа.
|
||||
|
||||
Параметры:
|
||||
-----------
|
||||
request : HttpRequest
|
||||
Объект HTTP-запроса для отправки сообщений через Django messages framework
|
||||
|
||||
obj : django.db.models.Model
|
||||
Сохраненный объект модели (уже сохранен в БД).
|
||||
Из этого объекта автоматически извлекается verbose_name модели через obj._meta.verbose_name
|
||||
Также используется для получения старого значения при редактировании.
|
||||
|
||||
is_new : bool
|
||||
True если создается новая запись, False если редактируется существующая.
|
||||
Определяет тип сообщения (green success для нового или warning для переименования).
|
||||
|
||||
related_article : django.db.models.Model или None
|
||||
Связанная статья (если есть). Если None, ссылка не добавляется в сообщение.
|
||||
Обычно это поле вида k_model_to_article из модели.
|
||||
При редактировании может содержать информацию о типе и содержимом статьи.
|
||||
|
||||
obj_field_name : str, опционально
|
||||
Имя основного поля объекта для получения текущего значения.
|
||||
По умолчанию 's_label' (для TbLabel).
|
||||
Примеры: 's_artist' (для TbArtist), 's_style_name' (для TbMusicStyle)
|
||||
|
||||
article_title_field : str, опционально
|
||||
Имя поля статьи для получения названия статьи.
|
||||
По умолчанию 's_article_title' (для TbArticle).
|
||||
Обычно это поле одинаково у всех моделей статей.
|
||||
|
||||
Отправляемые сообщения:
|
||||
-----------------------
|
||||
Новая запись (is_new=True):
|
||||
- GREEN SUCCESS: "Лейбл «NAME» создан успешно. Статья создана автоматически."
|
||||
- С ссылкой: "Проверить/Отредактировать статью →"
|
||||
|
||||
Переименование (is_new=False, имя изменилось):
|
||||
- YELLOW WARNING: "Лейбл «OLD» переименован на «NEW». ПРОВЕРЬТЕ СВЯЗАННУЮ СТАТЬЮ."
|
||||
- С ссылкой: "Проверить/Отредактировать статью →"
|
||||
|
||||
Обновление (is_new=False, имя не изменилось):
|
||||
- GREEN SUCCESS: "Лейбл «NAME» обновлен. Связанная статья: «ARTICLE_TITLE»."
|
||||
- С ссылкой: "Проверить/Отредактировать статью →"
|
||||
|
||||
Пример использования в admin.py (максимально чистый и поджарый код):
|
||||
-----------------------------------------------------------------------
|
||||
class LabelAdmin(admin.ModelAdmin):
|
||||
def save_model(self, request, obj, form, change):
|
||||
# Основной механизм сохранения Django (создает статью если нужно)
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
# Отправляем информативное сообщение админу
|
||||
# verbose_name берется автоматически из obj._meta.verbose_name
|
||||
# старое значение получается из БД при необходимости
|
||||
generate_admin_save_message(
|
||||
request=request,
|
||||
obj=obj,
|
||||
is_new=not change, # Django: change=False для новых, True для существующих
|
||||
related_article=obj.k_label_to_article,
|
||||
obj_field_name='s_label',
|
||||
)
|
||||
"""
|
||||
# Получаем текущее значение основного поля
|
||||
current_field_value = getattr(obj, obj_field_name, '')
|
||||
|
||||
# Инициализируем для использования в сообщениях (если related_article есть, перезапишем)
|
||||
article_title = ''
|
||||
article_link = ''
|
||||
article_info = ''
|
||||
|
||||
# Формируем ссылку на редактирование статьи и собираем информацию о ней
|
||||
if related_article:
|
||||
article_title = getattr(related_article, article_title_field, 'Статья')
|
||||
article_link = (f' <a href=\'../../../tbarticle/{related_article.pk}/change/\''
|
||||
f' target=\'_blank\'>Проверить/Отредактировать статью →</a>')
|
||||
|
||||
# Собираем информацию о статье для более подробного сообщения
|
||||
article_info = (f' [{getattr(related_article, 'l_article_type', '???')}]'
|
||||
f' ({getattr(related_article, 's_article_title_html', '<i>???</i>')})')
|
||||
|
||||
# Генерируем сообщение в зависимости от типа операции
|
||||
if is_new:
|
||||
# СОЗДАНИЕ НОВОЙ ЗАПИСИ - показываем зеленый успех
|
||||
msg = f'[OK] {obj._meta.verbose_name} «{current_field_value}» создан успешно.'
|
||||
if related_article:
|
||||
msg += (f' Связанная статья «{article_title}» создана автоматически. >>'
|
||||
f' {article_info} {article_link}')
|
||||
else:
|
||||
msg += ' [ОЙ-ОЙ-ОЙ] СТАТЬЯ НЕ БЫЛА СОЗДАНА. ЭТО НЕ ДОЛЖНО БЫЛО СЛУЧИТЬСЯ!'
|
||||
messages.success(request, mark_safe(msg))
|
||||
|
||||
else:
|
||||
# РЕДАКТИРОВАНИЕ СУЩЕСТВУЮЩЕЙ ЗАПИСИ
|
||||
# Название изменилось или нет - показываем информацию о текущем состоянии и связанной статье
|
||||
msg = f'[OK] {obj._meta.verbose_name} «{current_field_value}» обновлен.'
|
||||
if related_article:
|
||||
msg += f' Связанная статья: «{article_title}» >> {article_info} {article_link}'
|
||||
messages.success(request, mark_safe(msg))
|
||||
|
||||
Reference in New Issue
Block a user