Django admin实现文本字段字段变更列表页面换行和空格正常显示
问题背景
使用admin视图在Django后台绑定模型后,可以方便的进行底层的增删改查修改通过网页的数据表。
在实际工作中,有些数据字段存储的是json或者其他包含换行符和空格的文本内容。该文本内容在编辑信息页面上正常情况下可能会出现换行和空格,如下:
但在更改列表页面上,所有空格和换行都会被省略,导致可读性较差,如下:
原因
原因其实是因为在编辑详情页中,存放文本的标签是文本区域,该标签的文本内容不会忽略换行符和空格。使用浏览器的开发者工具,可以看到如下代码:
<textarea name="lang_content" cols="40" rows="10" class="vLargeTextField" required="" id="id_lang_content">{
"en": "this is a content",
"zh-hant": "這是默認正文內容"
}</textarea>
在changelist页面上,默认是直接使用td标签,即直接放在表格单元格中。此时,所有连续的空格和换行符将根据 HTML 标准处理为单个空格:
<td class="field-lang_content">{
"en": "this is a content",
"zh-hant": "這是默認正文內容"
}</td>
解决方案
以 test_record 表的简单管理视图为例。
表结构:
CREATE TABLE `test_table` (
`id` bigint(11) unsigned NOT NULL AUTO_INCREMENT COMMENT '自增主键',
`title` varchar(255) NOT NULL DEFAULT '0',
`content` varchar(255) NOT NULL,
`lang_content` text NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4
models.py:
# coding=utf-8
from django.db import models
class TestRecord(models.Model):
class Meta:
db_table = "test_record"
db_tablespace = 'test_db'
id = models.AutoField(primary_key=True, verbose_name="id")
title = models.CharField(max_length=255)
content = models.CharField(max_length=255)
lang_content = models.TextField()
admin.py
from django.contrib import admin
from django.utils.html import format_html
from .models import TestRecord
@admin.register(TestRecord)
class TestRecordAdmin(admin.ModelAdmin):
list_display = ('id', 'title', 'content', 'lang_content', 'lang_content_view')
使用list_editable
将lang_content放入list_editable中,如下:标签将用于更改lang_content内容,因此空格和行可以正确显示break:
同时lang_content字段可以直接在changelist页面编辑,无法满足该字段在changelist页面只读但不可编辑的要求,相当于编辑功能和显示功能强行绑定,无法分开,缺乏灵活性。
使用format_html——满足只读要求
django.utils.html中提供了format_html函数,可用于转义并渲染所有HTML格式的输出内容。
所以可以在admin类中定义一个专门负责显示lang_content内容的实例方法,将lang_content内容用pre或textarea标签包裹起来,然后在format_html转义之后返回。这种方法比较灵活,还可以通过调整标签的属性来自定义输出效果——比如设置高度(行)、宽度(列)等。
代码如下
def lang_content_view(self, obj):
# return format_html('<textarea cols=40 rows={} readonly>{}</textarea>', obj.lang_content.count('\n')+1, obj.lang_content)
return format_html('<pre>{}</pre>', obj.lang_content)
显示效果如下:
对应网页代码如下:
<td class="field-lang_content_view"><pre>{
"en": "this is a content",
"zh-hant": "這是默認正文內容"
}</pre></td>
版权声明
本文仅代表作者观点,不代表Code前端网立场。
本文系作者Code前端网发表,如需转载,请注明页面地址。
发表评论:
◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。