Проблема

Представьте, что у вас есть модель 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') продолжает работать по ориги­нальному полю в базе данных.

Теперь админка выглядит опрятно, а типографика на сайте остается безупречной!