diff --git a/lpon_site/frontend/admin.py b/lpon_site/frontend/admin.py index 2d73f36..1e7e92e 100644 --- a/lpon_site/frontend/admin.py +++ b/lpon_site/frontend/admin.py @@ -50,6 +50,9 @@ def get_related_article_description(model_class): f' со всеми SEO-атрибутами и slag, но автоматика несовершенна.
 ') +# ============================================================================ +# МИКСИНЫ ДЛЯ АДМИНКИ +# ============================================================================ class RequestInFormMixin(admin.ModelAdmin): """ Миксин для передачи request объекта в форму. @@ -144,15 +147,18 @@ class CodeMirrorFormMixin(forms.ModelForm): # Применяем Textarea виджет с атрибутами self.fields[field_name].widget = Textarea(attrs=attrs) + # ============================================================================ # АДМИНИСТРИРОВАНИЕ TbImage # # Кастомня форма для админки TbImage -class TbImageAdminForm(forms.ModelForm): +class TbImageAdminForm(CodeMirrorFormMixin): """ Кастомная форма для TbImage в админке. Добавляет виртуальные поля для редактирования метаданных filer_image - (default_alt_text и default_caption), которые не хранятся в TbImage, но есть в filer_image + (default_alt_text и default_caption), которые не хранятся в TbImage, но есть в filer_image. + + Наследует от CodeMirrorFormMixin для поддержки редактора CodeMirror. """ # Виртуальные поля для заполнения метаданных filer_image alt_text = forms.CharField( @@ -192,13 +198,8 @@ class TbImageAdminForm(forms.ModelForm): def __init__(self, *args, **kwargs): """ При инициализации формы подгружаем текущие значения alt/caption из filer_image. + Настраиваем поля для работы с CodeMirror редактором. """ - # Атрибуты для активации CodeMirror редактора - codemirror_attrs = { - 'data-codemirror-editor': '1', - 'data-width': '100%', # Ширина для патча (100% займет полную ширину) - } - super().__init__(*args, **kwargs) # Если редактируем существующую запись, получаем текущие значения из filer @@ -212,37 +213,26 @@ class TbImageAdminForm(forms.ModelForm): self.fields['title_text'].initial = filer_image.default_caption or '' self.fields['copyright_text'].initial = filer_image.author or '' - # Активируем CodeMirror и устанавливаем CSS-классы для виртуальных полей - self.fields['alt_text'].widget = Textarea(attrs={ - **codemirror_attrs, - 'class': 'codemirror-width-m', - }) - self.fields['title_text'].widget = Textarea(attrs={ - **codemirror_attrs, - 'class': 'codemirror-width-l', - }) - self.fields['copyright_text'].widget = Textarea(attrs={ - **codemirror_attrs, - 'class': 'codemirror-width-m', - }) except Exception: # Если ошибка при получении filer_image, просто оставляем пустые значения pass - # Активируем CodeMirror и устанавливаем классы для реальных полей - self.fields['s_img_src_url'].widget = Textarea(attrs={ - **codemirror_attrs, - 'data-language': 'url', - 'class': 'codemirror-width-xl', - }) - self.fields['i_img_sort'].widget = Textarea(attrs={ - **codemirror_attrs, - 'class': 'codemirror-width-s codemirror-no-lines', - }) - self.fields['f_img_confidence_score'].widget = Textarea(attrs={ - **codemirror_attrs, - 'class': 'codemirror-width-s codemirror-no-lines', - }) + # Активируем CodeMirror для виртуальных полей + self.setup_codemirror_field('alt_text', language='text', + css_class='codemirror-width-m codemirror-no-lines') + self.setup_codemirror_field('title_text', language='text', + css_class='codemirror-width-l codemirror-no-lines') + self.setup_codemirror_field('copyright_text', language='text', + css_class='codemirror-width-m codemirror-no-lines') + + # Активируем CodeMirror для реальных полей + self.setup_codemirror_field('s_img_src_url', language='url', + css_class='codemirror-width-xl codemirror-no-lines') + self.setup_codemirror_field('i_img_sort', language='text', + css_class='codemirror-width-s codemirror-no-lines') + self.setup_codemirror_field('f_img_confidence_score', language='text', + css_class='codemirror-width-s codemirror-no-lines') + # Админка для TbImage с кастомной формой class ImageAdmin(admin.ModelAdmin): @@ -251,18 +241,10 @@ class ImageAdmin(admin.ModelAdmin): Позволяет пользователю заполнить default_alt_text и default_caption для картинки в filer прямо в админке TbImage, без необходимости отдельного редактирования filer. + + Использует TbImageAdminForm с наследованием от CodeMirrorFormMixin для поддержки CodeMirror. """ - form = TbImageAdminForm # Используем кастомную форму с виртуальными полями - - # Подключаем JS через Media (правильный способ!) - class Media: - css = { - 'all': ('codemirror/codemirror-styles.css',) # Стили для CodeMirror - } - js = ( - 'codemirror/editor.js', # Основной CodeMirror - 'codemirror/codemirror-patch.js', # Патч для управления высотой/шириной - ) + form = TbImageAdminForm # Используем кастомную форму с виртуальными полями (Media подключится через миксин) list_display = ('id', 'image_thumbnail', 'image', '_display_alt_text', 'i_img_sort', 't_img_created') list_display_links = ('id', 'image_thumbnail', 'image') @@ -415,8 +397,10 @@ class MusicStyleAdminForm(CodeMirrorFormMixin): super().__init__(*args, **kwargs) # Конфигурируем поля для CodeMirror - self.setup_codemirror_field('s_style_name', language='text', css_class='codemirror-width-xl codemirror-no-lines') - self.setup_codemirror_field('j_style_synonyms', language='json', css_class='codemirror-width-l codemirror-min-height-5') + self.setup_codemirror_field('s_style_name', language='text', + css_class='codemirror-width-xl codemirror-no-lines') + self.setup_codemirror_field('j_style_synonyms', language='json', + css_class='codemirror-width-l codemirror-min-height-5') # Админка для TbMusicStyle с кастомной формой MusicStyleAdminForm class MusicStyleAdmin(admin.ModelAdmin): @@ -467,8 +451,10 @@ class ArtistAdminForm(CodeMirrorFormMixin): super().__init__(*args, **kwargs) # Конфигурируем поля для CodeMirror - self.setup_codemirror_field('s_artist', language='text', css_class='codemirror-width-xl codemirror-no-lines') - self.setup_codemirror_field('j_artist_metadata', language='json', css_class='codemirror-width-l codemirror-min-height-5') + self.setup_codemirror_field('s_artist', language='text', + css_class='codemirror-width-xl codemirror-no-lines') + self.setup_codemirror_field('j_artist_metadata', language='json', + css_class='codemirror-width-l codemirror-min-height-5') # Админка для TbArtist с кастомной формой ArtistAdminForm class ArtistAdmin(admin.ModelAdmin): @@ -520,8 +506,10 @@ class LabelAdminForm(CodeMirrorFormMixin): super().__init__(*args, **kwargs) # Конфигурируем поля для CodeMirror - self.setup_codemirror_field('s_label', language='text', css_class='codemirror-width-xl codemirror-no-lines') - self.setup_codemirror_field('j_label_metadata', language='json', css_class='codemirror-width-l codemirror-min-height-5') + self.setup_codemirror_field('s_label', language='text', + css_class='codemirror-width-xl codemirror-no-lines') + self.setup_codemirror_field('j_label_metadata', language='json', + css_class='codemirror-width-l codemirror-min-height-5') def clean(self): """ @@ -634,8 +622,10 @@ class SellerAdminForm(CodeMirrorFormMixin): super().__init__(*args, **kwargs) # Конфигурируем поля для CodeMirror - self.setup_codemirror_field('s_seller', language='text', css_class='codemirror-width-l codemirror-no-lines') - self.setup_codemirror_field('j_seller_metadata', language='json', css_class='codemirror-width-xl codemirror-min-height-5') + self.setup_codemirror_field('s_seller', language='text', + css_class='codemirror-width-l codemirror-no-lines') + self.setup_codemirror_field('j_seller_metadata', language='json', + css_class='codemirror-width-xl codemirror-min-height-5') # Админ для продавца (Seller) class SellerAdmin(admin.ModelAdmin): @@ -654,14 +644,7 @@ class SellerAdmin(admin.ModelAdmin): }), ('Связанная публикация', { 'fields': ('k_seller_to_article', ), - 'description': 'Прикреп­ленная статья (если есть) будет отображаться на странице продавца' - ' на сайте. Также позволяет получать список всех предложений продавца, управлять' - ' SEO-атрибутами для улучшения видимости поисковых систем, иметь красивый' - ' slag для URL-странички, подсчитывать число просмотров и добавлений' - ' в избранные. ОЧЕНЬ РЕКОМЕН­ДУЕТСЯ СОЗДАВАТЬ' - ' И ПРИВЯЗЫВАТЬ СТАТЬЮ ВРУЧНУЮ. Если публикация не создана вручную,' - ' то она будет создана автоматически (пустая) при сохранении продавца,' - ' со всеми SEO-атрибутами и slag, но автоматика несовершенна.
 ', + 'description': get_related_article_description(TbSeller), # 'classes': ('collapse',), }), ('Служебная информация', { @@ -692,9 +675,12 @@ class SourceAdminForm(CodeMirrorFormMixin): super().__init__(*args, **kwargs) # Конфигурируем поля для CodeMirror - self.setup_codemirror_field('s_source_name', language='text', css_class='codemirror-width-l codemirror-no-lines') - self.setup_codemirror_field('s_source_url', language='url', css_class='codemirror-width-xl codemirror-no-lines') - self.setup_codemirror_field('j_source_metadata', language='json', css_class='codemirror-width-l codemirror-min-height-5') + self.setup_codemirror_field('s_source_name', language='text', + css_class='codemirror-width-l codemirror-no-lines') + self.setup_codemirror_field('s_source_url', language='url', + css_class='codemirror-width-xl codemirror-no-lines') + self.setup_codemirror_field('j_source_metadata', language='json', + css_class='codemirror-width-l codemirror-min-height-5') # class SourceAdmin(admin.ModelAdmin): @@ -769,4 +755,3 @@ admin.site.register(TbOfferHistory, OfferHistoryAdmin) # ============================================================================ -