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)
# ============================================================================
-