Как правильно ограничить длину текста в CKEditor 5 без учёта HTML-разметки
Как правильно ограничить длину текста в CKEditor 5 без учёта HTML-разметки
При использовании CKEditor 5 в Django-проектах многие сталкиваются с проблемой: стандартный параметр `max_length` считает длину HTML-кода, а не видимого текста.
Рассмотрим решение этой проблемы.
Стандартное определение поля:
content_short = CKEditor5Field(
max_length=600, # Считает ВСЕ символы, включая HTML-теги
verbose_name='Краткий текст'
)
Для решения проблемы с подсчётом длины текста без HTML-разметки в CKEditor5Field
предлагаю следующие доработки:
Пример:
Видимый текст: "Привет, мир!" (12 символов)
HTML-код:
<p><strong>Привет</strong>, мир!</p>
(32 символа)
Решение
1. Валидация на уровне модели
from django.core.exceptions import ValidationError
from django.utils.html import strip_tags
class Article(models.Model):
content_short = CKEditor5Field(
max_length=2000, # Лимит с запасом для HTML
blank=True,
null=True,
verbose_name='Краткий текст',
)
def clean(self):
super().clean()
if self.content_short:
clean_text = strip_tags(self.content_short)
if len(clean_text) > 600:
raise ValidationError(
f'Максимум 600 символов. Сейчас: {len(clean_text)}'
)
2. JavaScript-счетчик для админки
static/js/ckeditor_counter.js
:
document.addEventListener('DOMContentLoaded', () => {
document.querySelectorAll('.django-ckeditor-widget').forEach(widget => {
const counter = document.createElement('div');
counter.className = 'ckeditor-counter';
widget.appendChild(counter);
const editor = widget.querySelector('.ck-editor__editable');
const update = () => {
const text = editor.innerText;
counter.textContent = `${text.length}/600 символов`;
counter.style.color = text.length > 600 ? 'red' : '#666';
};
editor.addEventListener('input', update);
update();
});
});
Подключение в админке:
class Media:
css = {'all': ('css/ckeditor_counter.css',)}
js = ('js/ckeditor_counter.js',)
3. Валидация в формах
class ArticleForm(forms.ModelForm):
def clean_content_short(self):
content = self.cleaned_data['content_short']
if content and len(strip_tags(content)) > 600:
raise forms.ValidationError("Превышен лимит в 600 символов")
return content
Полная реализация
Модель - оставляем
max_length
с запасом для HTMLВалидация - проверяем чистый текст через
strip_tags()
Интерфейс - JS-счетчик для наглядности
Защита - валидация на всех уровнях (клиент/сервер)
Альтернативные подходы
Кастомное поле:
class CleanTextLengthField(CKEditor5Field):
def __init__(self, *args, clean_length=600, **kwargs):
self.clean_length = clean_length
super().__init__(*args, **kwargs)
def clean(self, value, model_instance):
clean_text = strip_tags(value)
if len(clean_text) > self.clean_length:
raise ValidationError(...)
return super().clean(value, model_instance)
Плагин CKEditor - можно создать кастомный плагин для подсчёта символов.
Вывод
Предложенное решение обеспечивает:
Корректный подсчёт только видимого текста
Визуальный контроль при вводе
Надёжную валидацию на сервере
Сохранение всех возможностей CKEditor
Для реализации достаточно скопировать код из примеров и адаптировать под свой проект.
### Советы по публикации:
1. Добавьте скриншоты интерфейса с примером работы
2. Включите раздел "Частые вопросы"
3. Добавьте примеры ошибок и их решений
4. Упомяните вашу версию Django и django-ckeditor
Категория: Программирование | автор: fominyh_vv
Опубликовано: 18-04-2025 15:12