You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Django Admin仅查看权限用户RichTextField格式化及KeyError问题解决

问题描述

我有一个仅拥有模型查看权限的用户,该模型包含RichTextField,但该用户查看数据时内容未按HTML格式化。我知道在list_display中可以用以下方法处理:

def what_field(self, obj):
       return format_html(obj.what)

原本打算把Django Admin作为管理主页面,Activity模型包含what、when、where等字段,超级用户登录查看该模型时,借助django-ckeditor能正常显示RichTextField内容,但仅拥有查看权限的用户不行。

核心问题:

  • 如何在Django Admin仅查看权限的页面中使用strip_tags或format_html?
  • 当前重写get_form方法时出现KeyError: 'what'错误,项目使用了django-jazzmin。

model.py

from django.db import models
from django.utils.translation import gettext_lazy as _
from django.conf import settings
from datetime import date, datetime
from ckeditor.fields import RichTextField

class Activity(models.Model):
    what        = RichTextField(verbose_name=_('What'))
    where       = RichTextField(verbose_name=_('Where'))
    when        = models.DateField(verbose_name=_('When'))
    why         = RichTextField(verbose_name=_('Why'))
    who         = RichTextField(verbose_name=_('Who'))
    created_on  = models.DateTimeField(auto_now_add=True)
    modified_on = models.DateTimeField(auto_now=True)
    author      = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.DO_NOTHING, verbose_name=_('Author'))
    
    class Meta:
        verbose_name = _('Activity Announcements')
        verbose_name_plural = _('Activity Announcements')

    def __str__(self):
        from django.utils.html import strip_tags
        return '%s' % (strip_tags(self.what))

admin.py

from django.contrib import admin
from django.utils.translation import gettext_lazy as _
from .models import *

from django.utils.html import format_html

@admin.register(Activity)
class ActivityAdmin(admin.ModelAdmin):
    
    inlines = [ParticipantsInline, Aar_uploadInline]
    list_display = ('__str__','created_on',)
    
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        if obj:
            form.base_fields['what'].initial = format_html(obj.what)
        return form

错误信息

KeyError at /admin/activity_announcements/activity/1/change/
'what'
Request Method: GET
Request URL:    http://localhost:8000/admin/activity_announcements/activity/1/change/
Django Version: 4.0.5
Exception Type: KeyError
Exception Value:    
'what'
Exception Location: /app/activity_announcements/admin.py, line 29, in get_form
Python Executable:  /py/bin/python
Python Version: 3.9.9
Python Path:    
['/app',
 '/usr/local/lib/python39.zip',
 '/usr/local/lib/python3.9',
 '/usr/local/lib/python3.9/lib-dynload',
 '/py/lib/python3.9/site-packages']
Server time:    Fri, 21 Oct 2022 12:24:19 +0800

解决方案

1. 修复KeyError: 'what'错误

出现这个错误是因为仅拥有查看权限的用户,其表单不会包含可编辑字段,form.base_fields里自然找不到what字段。修改get_form方法,先判断字段是否存在:

def get_form(self, request, obj=None, **kwargs):
    form = super().get_form(request, obj, **kwargs)
    if obj and 'what' in form.base_fields:
        form.base_fields['what'].initial = format_html(obj.what)
    return form

2. 让仅查看权限的用户看到格式化后的HTML内容

对于无修改权限的用户,Django Admin会显示只读页面,通过自定义只读字段的显示方法来实现HTML格式化:

from django.utils.html import format_html, strip_tags

@admin.register(Activity)
class ActivityAdmin(admin.ModelAdmin):
    inlines = [ParticipantsInline, Aar_uploadInline]
    list_display = ('__str__','created_on',)
    
    # 自定义格式化显示方法
    def formatted_what(self, obj):
        return format_html(obj.what)
    formatted_what.short_description = _('What')
    
    def formatted_where(self, obj):
        return format_html(obj.where)
    formatted_where.short_description = _('Where')
    
    def formatted_why(self, obj):
        return format_html(obj.why)
    formatted_why.short_description = _('Why')
    
    def formatted_who(self, obj):
        return format_html(obj.who)
    formatted_who.short_description = _('Who')
    
    # 根据用户权限返回对应只读字段
    def get_readonly_fields(self, request, obj=None):
        if not request.user.has_perm('activity_announcements.change_activity'):
            return ('formatted_what', 'formatted_where', 'when', 'formatted_why', 'formatted_who', 'created_on', 'modified_on', 'author')
        return ('created_on', 'modified_on', 'author')
    
    # 修复后的get_form方法
    def get_form(self, request, obj=None, **kwargs):
        form = super().get_form(request, obj, **kwargs)
        if obj and 'what' in form.base_fields:
            form.base_fields['what'].initial = format_html(obj.what)
        return form

3. 列表页的HTML格式化(可选)

如果需要在列表页也显示格式化后的内容,修改list_display:

def what_field(self, obj):
    return format_html(obj.what)
what_field.short_description = _('What')

list_display = ('what_field', 'created_on',)

内容的提问来源于stack exchange,提问作者Markmeplease

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.16 11:05:21