add: В админку добавлен типограф etpgrf. Удалены ненужные поля из модели.
This commit is contained in:
@@ -1,10 +1,72 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
from django.contrib import admin
|
||||
from django import forms
|
||||
from web.models import TbDictumAndQuotes, TbAuthor, TbImages, TbOrigin
|
||||
|
||||
try:
|
||||
from etpgrf.typograph import Typographer
|
||||
from etpgrf.layout import LayoutProcessor
|
||||
from etpgrf.hyphenation import Hyphenator
|
||||
except ImportError:
|
||||
# Заглушка, если библиотека не установлена
|
||||
class Typographer:
|
||||
def __init__(self, **kwargs): pass
|
||||
def process(self, text): return text
|
||||
class LayoutProcessor:
|
||||
def __init__(self, **kwargs): pass
|
||||
class Hyphenator:
|
||||
def __init__(self, **kwargs): pass
|
||||
|
||||
|
||||
class DictumAdminForm(forms.ModelForm):
|
||||
# Виртуальные поля для настройки типографа
|
||||
etp_language = forms.ChoiceField(
|
||||
label="Язык типографики",
|
||||
choices=[('ru', 'Русский'), ('en', 'English'), ('ru,en', 'Ru + En')],
|
||||
initial='ru',
|
||||
required=False
|
||||
)
|
||||
etp_quotes = forms.BooleanField(
|
||||
label="Обработка кавычек",
|
||||
initial=True,
|
||||
required=False,
|
||||
help_text="Заменять прямые кавычки на «ёлочки» или “лапки”"
|
||||
)
|
||||
etp_hanging_punctuation = forms.ChoiceField(
|
||||
label="Висячая пунктуация",
|
||||
choices=[('no', 'Нет'), ('left', 'Слева'), ('right', 'Справа'), ('both', 'Обе стороны')],
|
||||
initial='left',
|
||||
required=False,
|
||||
help_text="Выносить кавычки за границу текстового блока"
|
||||
)
|
||||
etp_hyphenation = forms.BooleanField(
|
||||
label="Переносы",
|
||||
initial=True,
|
||||
required=False,
|
||||
help_text="Расставлять мягкие переносы (­)"
|
||||
)
|
||||
etp_sanitize = forms.BooleanField(
|
||||
label="Санитайзер (HTML)",
|
||||
initial=False,
|
||||
required=False,
|
||||
help_text="Очищать HTML теги перед обработкой"
|
||||
)
|
||||
etp_mode = forms.ChoiceField(
|
||||
label="Режим вывода",
|
||||
choices=[('mixed', 'Смешанный (Mixed)'), ('unicode', 'Юникод (Unicode)'), ('mnemonic', 'Мнемоники')],
|
||||
initial='mixed',
|
||||
required=False,
|
||||
help_text="Формат спецсимволов"
|
||||
)
|
||||
|
||||
class Meta:
|
||||
model = TbDictumAndQuotes
|
||||
fields = '__all__'
|
||||
|
||||
|
||||
# Register your models here.
|
||||
class AdmDictumAndQuotesAdmin(admin.ModelAdmin):
|
||||
form = DictumAdminForm
|
||||
search_fields = ['id', 'szIntro', 'szContent', ]
|
||||
list_display = ('id', 'szIntro', 'szContent', 'tag_list', 'iViewCounter', 'dtEdited', )
|
||||
list_display_links = ('id', 'szIntro', 'szContent', )
|
||||
@@ -13,12 +75,109 @@ class AdmDictumAndQuotesAdmin(admin.ModelAdmin):
|
||||
actions_on_top = False
|
||||
actions_on_bottom = True
|
||||
actions_selection_counter = True
|
||||
# погасить кнопку "Добавить" в интерфейсе админки
|
||||
# def has_add_permission(self, request):
|
||||
# return False
|
||||
# fieldsets = (
|
||||
# (None, {'fields': ('szIntro', 'iViewCounter', 'tags',)}),
|
||||
# )
|
||||
|
||||
fieldsets = (
|
||||
(None, {
|
||||
'fields': ('szIntro', 'szContent', 'kAuthor', 'kOrigin', 'kImages', 'tags', 'bIsChecked')
|
||||
}),
|
||||
('Настройки типографа (Etpgrf)', {
|
||||
'classes': ('collapse',),
|
||||
'fields': (
|
||||
('etp_language', 'etp_mode'),
|
||||
('etp_quotes', 'etp_sanitize'),
|
||||
('etp_hyphenation', 'etp_hanging_punctuation'),
|
||||
),
|
||||
'description': 'Настройки применяются при сохранении. Результат записывается в скрытые HTML-поля.'
|
||||
}),
|
||||
('HTML Результат (ReadOnly)', {
|
||||
'classes': ('collapse',),
|
||||
'fields': ('szIntroHTML', 'szContentHTML'),
|
||||
}),
|
||||
('Служебное', {
|
||||
'classes': ('collapse',),
|
||||
'fields': ('iViewCounter', 'imFileOG', 'bTypograph') # bTypograph kept for compatibility
|
||||
})
|
||||
)
|
||||
readonly_fields = ('szIntroHTML', 'szContentHTML', 'iViewCounter')
|
||||
|
||||
def save_model(self, request, obj, form, change):
|
||||
# 1. Читаем базовые настройки
|
||||
langs = form.cleaned_data.get('etp_language', 'ru').split(',')
|
||||
|
||||
# 2. Собираем LayoutProcessor
|
||||
layout_option = False
|
||||
# Включаем layout по умолчанию с базовыми настройками (инициалы, юниты)
|
||||
layout_option = LayoutProcessor(
|
||||
langs=langs,
|
||||
process_initials_and_acronyms=True,
|
||||
process_units=True
|
||||
)
|
||||
|
||||
# 3. Собираем Hyphenator
|
||||
hyphenation_enabled = form.cleaned_data.get('etp_hyphenation', True)
|
||||
hyphenation_option = False
|
||||
if hyphenation_enabled:
|
||||
hyphenation_option = Hyphenator(
|
||||
langs=langs,
|
||||
max_unhyphenated_len=12
|
||||
)
|
||||
|
||||
# 4. Читаем Sanitizer
|
||||
sanitizer_enabled = form.cleaned_data.get('etp_sanitize', False)
|
||||
sanitizer_option = None
|
||||
if sanitizer_enabled:
|
||||
sanitizer_option = 'etp'
|
||||
|
||||
# 5. Читаем Hanging Punctuation
|
||||
hanging_val = form.cleaned_data.get('etp_hanging_punctuation', 'no')
|
||||
hanging_option = None
|
||||
if hanging_val != 'no':
|
||||
hanging_option = hanging_val
|
||||
|
||||
# 6. Собираем общие опции
|
||||
options = {
|
||||
'langs': langs,
|
||||
'process_html': True,
|
||||
'quotes': form.cleaned_data.get('etp_quotes', True),
|
||||
'layout': layout_option,
|
||||
'unbreakables': True,
|
||||
'hyphenation': hyphenation_option,
|
||||
'symbols': True,
|
||||
'hanging_punctuation': hanging_option,
|
||||
'mode': form.cleaned_data.get('etp_mode', 'mixed'),
|
||||
'sanitizer': sanitizer_option,
|
||||
}
|
||||
|
||||
# Инициализируем типограф с настройками из формы
|
||||
try:
|
||||
# DEBUG: Проверка, какой класс используется
|
||||
if Typographer.__module__ == __name__: # Если класс определен в этом же файле (заглушка)
|
||||
self.message_user(request, "ВНИМАНИЕ: Используется заглушка Typographer! Библиотека etpgrf не найдена.", level='WARNING')
|
||||
|
||||
t = Typographer(**options)
|
||||
|
||||
# Обрабатываем контент
|
||||
if obj.szContent:
|
||||
# В онлайн-типографе используется .process(text)
|
||||
old_html = obj.szContentHTML or ""
|
||||
processed = t.process(obj.szContent)
|
||||
obj.szContentHTML = processed
|
||||
|
||||
# DEBUG: Проверка изменений
|
||||
if processed != old_html and processed != obj.szContent:
|
||||
self.message_user(request, f"Типограф: szContentHTML обновлен (len changed: {len(old_html)} -> {len(processed)})", level='INFO')
|
||||
|
||||
# Обрабатываем интро
|
||||
if obj.szIntro:
|
||||
obj.szIntroHTML = t.process(obj.szIntro)
|
||||
|
||||
except Exception as e:
|
||||
# Fallback if processing fails
|
||||
self.message_user(request, f"Ошибка типографа: {e}", level='ERROR')
|
||||
if not obj.szContentHTML: obj.szContentHTML = obj.szContent
|
||||
if not obj.szIntroHTML: obj.szIntroHTML = obj.szIntro
|
||||
|
||||
super().save_model(request, obj, form, change)
|
||||
|
||||
def get_queryset(self, request):
|
||||
return super().get_queryset(request).prefetch_related('tags')
|
||||
@@ -64,3 +223,4 @@ admin.site.register(TbDictumAndQuotes, AdmDictumAndQuotesAdmin)
|
||||
admin.site.register(TbOrigin, AdmOrigin)
|
||||
admin.site.register(TbImages, AdmImages)
|
||||
admin.site.register(TbAuthor, AdmAuthor)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user