Чистые, типографированные заголовки в админке Django: убираем HTML-мнемоники
Библиотека типографа etpgrf написана на Python, и потому его использование в Django — наиболее распространенный случай. Когда в Django вы храните в базе данных типографированный текст (с HTML-мнемониками: неразрывными пробелами , мягкими переносами ­ и тому подобное), то стандартный список в админке Django превращается в не очень удобочитаемую кашу из спецсимволов. Рассказываем, как это исправить за пару строк кода.
Проблема
Представьте, что у вас есть модель Post в которой хранятся записи блога, и вы прогнали заголовки через типограф (например, через наш онлайн-типограф или с помощью библиотеки etpgrf). В базе данных заголовок выглядит так:
Политика безопасности и конфи­денциаль­ности
На сайте это будет отлично выглядеть для браузера, но в панели администратора или контент-менеджера это ужасно, так как Django «маскирует» & и все HTML-мнемоники будут видны во всей красе. В списке объектов (Change List) будет виден «сырой» HTML-код, и читать такое сложно, особенно если мнемоник много.
Решение
Нам нужно, чтобы в списке (list_display) отображался «чистый» текст, а в форме редактирования оставался исходный HTML (чтобы его было легче править).
Для этого мы добавим в класс ModelAdmin специальный метод, который будет декодировать HTML-мнемоники перед выводом в админку.
Шаг 1. Импортируем модуль html
В Python есть встроенная библиотека html, которая умеет делать unescape — превращать мнемоники, например или ­, unicode. превратится в неразрывный пробел, а ­ в мягкий перенос.
Шаг 2. Создаем метод в админке
В файле admin.py:
from django.contrib import admin
import html
from .models import Post
@admin.register(Post)
class PostAdmin(admin.ModelAdmin):
# В list_display указываем не поле 'title', а наш метод 'clean_title'
list_display = ('clean_title', 'is_published', 'published_at')
# ... остальные настройки ...
# Декоратор @admin.display позволяет настроить название колонки и сортировку
@admin.display(description='Заголовок', ordering='title')
def clean_title(self, obj):
# Декодируем HTML-сущности ( -> U+00A0)
return html.unescape(obj.title)
Как это работает?
- Метод
clean_titleполучает объект модели. html.unescape(obj.title)превращает HTML-мнемоники в Unicode: в символ неразрывного пробела (U+00A0);­— в мягкий перенос (U+00AD) и так далее.- Unicode не маскируется адимнкой Django, символы выглядят как обычный текст (или вообще не видны), поэтому список становится чистым и читаемым (и даже, более того, в списке уже будут типографированные поля
title). - При этом сортировка по колонке (
ordering='title') продолжает работать по оригинальному полю в базе данных.
Теперь админка выглядит опрятно, а типографика на сайте остается безупречной!