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')