【问题标题】:Creating a display-only (non-editable) Django admin field创建仅显示(不可编辑)的 Django 管理字段
【发布时间】:2016-02-04 05:37:10
【问题描述】:

是否可以构建一个自定义模型字段/小部件组合,它显示一个值但从不将任何内容写回数据库?我会专门在管理员表单中使用这个小部件。

我编写了自己的字段,它覆盖了formfield() 方法来声明自己的小部件类。它显示得很好,但是一旦在管理员中单击“保存”按钮,我就会收到验证错误:

This field is required.

考虑到我的小部件没有呈现表单字段,这是有道理的。但是,我想做的基本上是从更新过程中删除此字段:无论何时在管理员中使用,它都不应该在 SQL UPDATE 中提及。

这可能吗?

这是我目前的代码草图:

class MyWidget(Widget):
    def render(self, name, value, attrs=None):
        if value is None:
            value = ""
        else:
            # pretty print the contents of value here
            return '<table>' + ''.join(rows) + '</table>'

class MyField(JSONField):
    def __init__(self, *args, **kwargs):
        kwargs['null'] = False
        kwargs['default'] = list
        super(MyField, self).__init__(*args, **kwargs)

    def formfield(self, **kwargs):
        defaults = {
            'form_class': JSONFormField,
            'widget': MyWidget,
        }
        defaults.update(**kwargs)
        return super(MyField, self).formfield(**defaults)

更新 1:用例是该字段表示审计日志。在内部,它将定期写入。然而,管理员永远不需要写它,它只需要以非常易读的格式呈现出来。

我没有在应用程序中使用任何其他 ModelForm,因此管理员是唯一的表单用户。我不想在管理类本身上实现该行为,因为该字段将在各种模型中重复使用,并且应该始终以相同的方式运行。

【问题讨论】:

  • 作为一个临时解决方案,我在我的小部件渲染器中添加了一个隐藏字段,但这感觉不对:现在我正在通过浏览器发送序列化的字段内容,然后对其进行反序列化返回,而不是仅仅从保存操作中删除这一字段。

标签: python django django-admin


【解决方案1】:

有多种方法可以在管理页面中创建只读字段。您对数据库存储的要求有点模糊,所以我通过选项。

你必须先在admin.py注册一个AdminModel:

from django.contrib import admin
from yourapp.models import YourModel

class YourAdmin(admin.ModelAdmin):
    pass

admin.site.register(YourModel, YourAdmin)

现在您可以为其添加不同的行为。例如,您可以添加编辑/添加页面中显示的字段列表:

class YourAdmin(admin.ModelAdmin):
    fields = ['field1', 'field2']

这可以是模型字段、模型属性或模型方法的名称。方法以只读方式显示。

如果您想让一个字段为只读,请显式添加:

class YourAdmin(admin.ModelAdmin):
    fields = ['field1', 'field2']
    readonly_fields = ['field2']

然后您可以选择通过添加同名方法来完全覆盖字段的显示。您甚至不需要具有该名称的模型字段/方法,然后:

class YourAdmin(admin.ModelAdmin):
    fields = ['field1', 'field2']
    readonly_fields = ['field2']

    def field2(self, obj):
        return '*** CLASSIFIED *** {}'.format(obj.field2)

使用django.utils.safestring.mark_safe,您也可以返回 HTML 代码。

管理员的所有其他选项都可用,除了小部件配置,因为它仅适用于可写字段。

【讨论】:

  • 感谢您的详细概述,非常好地总结了不同的选项!但是,我希望将此行为与字段类型本身相关联,因为我计划在各种模型中重复使用它,并且它将由应用程序专门写入(它基本上是一个审计日志),但始终是只读的管理员。
  • 这实际上是管理模型配置从数据模型移动到管理模型的原因。但是您可以对任何模型字段进行子类化,并通过检查该类型的字段从模型动态生成readonly_fields
【解决方案2】:

我可能对您想要什么有点困惑,但您可能想查看模型属性。这是我当前项目的示例。

模型中的代码:

class Textbook(models.Model):
    #other fields

    @property
    def NumWishes(self):
        return self.wishlist_set.count()

然后你就可以在管理页面上显示它了。

class Textbook_table(admin.ModelAdmin):
    fields = ["""attributes that are saved in the model"""]
    list_display = ("""attributes that are saved in the model""", 'NumWishes'')

所以现在我可以在管理页面中显示 NumWishes,但不需要使用模型创建。

【讨论】:

  • 嗯,我需要一个字段支持它,因为它是存储在数据库中的实际数据,并且将由我的应用程序修改。我只想在管理员中以更易读的格式呈现它,我不想在管理员中编辑它。
猜你喜欢
  • 1970-01-01
  • 2021-05-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-20
  • 1970-01-01
  • 1970-01-01
  • 2014-01-12
相关资源
最近更新 更多