diff --git a/lpon_site/frontend/admin.py b/lpon_site/frontend/admin.py
index dea8405..429365e 100644
--- a/lpon_site/frontend/admin.py
+++ b/lpon_site/frontend/admin.py
@@ -263,20 +263,6 @@ class ImageAdmin(admin.ModelAdmin):
logger.error(f'Ошибка при сохранении метаданных filer_image: {e}')
-# ============================================================================
-# Остальные ModelAdmin классы
-# ============================================================================
-
-class ArticleAdmin(admin.ModelAdmin):
- """Админ для статей"""
- list_display = ('id', 's_article_title', 'l_article_type', 'b_article_published', 't_article_created')
- list_filter = ('l_article_type', 'b_article_published', 't_article_created')
- search_fields = ('s_article_title', 'slug')
- prepopulated_fields = {'slug': ('s_article_title',)}
- readonly_fields = ('t_article_created', 't_article_updated')
- # filter_horizontal = ('k_article_to_styles',)
-
-
# ============================================================================
# АДМИНКА для музыкальных стилей, таблица TbMusicStyle
#
@@ -435,20 +421,84 @@ class ArtistAdmin(admin.ModelAdmin):
)
-class ItemAdmin(admin.ModelAdmin):
- """Админ для товаров"""
- list_display = ('id', 's_item', 't_item_date', 't_item_created')
- list_filter = ('t_item_date', 't_item_created')
- search_fields = ('s_item',)
- filter_horizontal = ('k_item_to_artist', 'k_item_to_style')
- readonly_fields = ('t_item_created', 't_item_updated')
+# ================
+# АДМИН-ПАНЕЛЬ ДЛЯ ЛЕЙБЛОВ/ИЗДАТЕЛЕЙ
+#
+# Кастомная форма
+class LabelAdminForm(forms.ModelForm):
+ """
+ Кастомная форма для админки лейблов (Label).
+ Добавляет виджеты CodeMirror для текстовых полей
+ """
+ class Meta:
+ model = TbLabel
+ fields = ('s_label', 'k_label_to_article', 'j_label_metadata',)
+
+ def __init__(self, *args, **kwargs):
+ """
+ При инициализации формы подгружаем
+ """
+ # Атрибуты для активации CodeMirror редактора
+ codemirror_attrs = {
+ 'data-codemirror-editor': '1',
+ 'data-width': '100%', # Ширина для патча (100% займет полную ширину)
+ }
+
+ super().__init__(*args, **kwargs)
+
+ # Активируем CodeMirror и устанавливаем классы для реальных полей
+ self.fields['s_label'].widget = Textarea(attrs={
+ **codemirror_attrs,
+ 'class': 'codemirror-width-xl codemirror-no-lines',
+ 'data-language': 'text',
+ })
+ self.fields['j_label_metadata'].widget = Textarea(attrs={
+ **codemirror_attrs,
+ 'class': 'codemirror-width-l codemirror-min-height-5',
+ 'data-language': 'json',
+ })
+
+# Админ для лейбла (Label)
class LabelAdmin(admin.ModelAdmin):
"""Админ для лейблов"""
+ form = LabelAdminForm # Используем кастомную форму с виджетами CodeMirror
+
+ # Подключаем JS через Media (правильный способ!)
+ class Media:
+ css = {
+ 'all': ('codemirror/codemirror-styles.css',) # Стили для CodeMirror
+ }
+ js = (
+ 'codemirror/editor.js', # Основной CodeMirror
+ 'codemirror/codemirror-patch.js', # Патч для управления высотой/шириной
+ )
list_display = ('id', 's_label', 't_label_created')
+ list_display_links = ('id', 's_label',)
search_fields = ('s_label',)
readonly_fields = ('t_label_created', 't_label_updated')
+ fieldsets = (
+ ('Основные данные о лейбле/издателе', {
+ 'fields': ('s_label', 'j_label_metadata',),
+ }),
+ ('Связанная публикация', {
+ 'fields': ('k_label_to_article', ),
+ 'description': 'Прикрепленная статья (если есть) будет отображаться на странице лейбла'
+ ' на сайте. Также позволяет получать список всех альбомов лейбла, управлять'
+ ' SEO-атрибутами для улучшения видимости поисковых систем, иметь красивый'
+ ' slag для URL-странички, подсчитывать число просмотров и добавлений'
+ ' в избранные. ОЧЕНЬ РЕКОМЕНДУЕТСЯ СОЗДАВАТЬ'
+ ' И ПРИВЯЗЫВАТЬ СТАТЬЮ ВРУЧНУЮ. Если публикация не создана вручную,'
+ ' то она будет создана автоматически (пустая) при сохранении лейбла,'
+ ' со всеми SEO-атрибутами и slag, но автоматика несовершенна.
',
+ # 'classes': ('collapse',),
+ }),
+ ('Служебная информация', {
+ 'fields': ('t_label_created', 't_label_updated'),
+ 'classes': ('collapse',),
+ }),
+ )
# ================
# АДМИН-ПАНЕЛЬ ДЛЯ ПРОДАВЦА/SELLER
@@ -595,6 +645,20 @@ class SourceAdmin(admin.ModelAdmin):
readonly_fields = ('t_source_created', 't_source_updated')
+# ============================================================================
+# Остальные ModelAdmin классы
+# ============================================================================
+
+
+class ItemAdmin(admin.ModelAdmin):
+ """Админ для товаров"""
+ list_display = ('id', 's_item', 't_item_date', 't_item_created')
+ list_filter = ('t_item_date', 't_item_created')
+ search_fields = ('s_item',)
+ filter_horizontal = ('k_item_to_artist', 'k_item_to_style')
+ readonly_fields = ('t_item_created', 't_item_updated')
+
+
class OfferAdmin(admin.ModelAdmin):
"""Админ для предложений"""
list_display = ('id', 's_offer', 'k_offer_to_item', 'f_offer_price', 'i_offer_quantity', 'i_offer_views')
@@ -604,6 +668,16 @@ class OfferAdmin(admin.ModelAdmin):
readonly_fields = ('s_offer_skip32', 't_offer_created', 't_offer_updated', 'i_offer_views', 'i_offer_favorites')
+class ArticleAdmin(admin.ModelAdmin):
+ """Админ для статей"""
+ list_display = ('id', 's_article_title', 'l_article_type', 'b_article_published', 't_article_created')
+ list_filter = ('l_article_type', 'b_article_published', 't_article_created')
+ search_fields = ('s_article_title', 'slug')
+ prepopulated_fields = {'slug': ('s_article_title',)}
+ readonly_fields = ('t_article_created', 't_article_updated')
+ # filter_horizontal = ('k_article_to_styles',)
+
+
class OfferHistoryAdmin(admin.ModelAdmin):
"""Админ для истории изменений офферов"""
list_display = ('id', 'k_history_to_offer', 'f_history_price', 'i_history_quantity', 't_history_created')