django admin如何在只读字段上显示小部件

Posted

技术标签:

【中文标题】django admin如何在只读字段上显示小部件【英文标题】:django admin how to display widget on readonly field 【发布时间】:2013-01-27 18:29:37 【问题描述】:

当字段为只读时,我想在 django admin 的字段上显示我的小部件。

admin.py

class AudioTrackAdminInline(admin.StackedInline):
    model = AudioTrack
    form = AudioTrackForm
    readonly_fields = ('file',)

forms.py

class AudioTrackForm(forms.ModelForm):
    class Meta:
        model = AudioTrack
        widgets =  'file': MediaFileInput,  # my widget

当文件不是只读时,它会显示小部件 OK。但是当我将它包含为只读时,我会看到文本行。 (如果只读,Django 不会使用我的表单)

如何让它在只读字段中使用表单?

如果我将我的字段设置为只读,如何显示另一个小部件?

【问题讨论】:

【参考方案1】:

我会说这是一个功能。

当字段设置为只读时,Django 使用display_for_field 函数对结果进行硬编码,您无法自定义它。

另一种方法是不将该字段设置为只读并覆盖formfield_for_dbfield,这是一个未记录的ModelAdmin 方法,并根据您的需要采取行动。

【讨论】:

覆盖formfield_for_dbfield 是危险的,因为用户可以提交POST 并篡改您打算只读的字段(或仅使用检查器启用它)。【参考方案2】:

另一种更灵活的解决方案是设置您希望以只读模式呈现的那些字段的“禁用”属性,覆盖您的管理类的 get_form(...) 方法:

def get_form(self, *args, **kwargs):

    form = super(SupplierAdmin, self).get_form(*args, **kwargs)

    for field_name in self.fake_readonly_fields:
        form.base_fields[field_name].disabled = True

    return form

请注意,我使用只读字段的名称不是来自通常的 self.readonly_fields,而是来自我命名为 self.fake_readonly_fields 的不同数组,以避免名称重叠

建议的解决方案(使用formfield_for_dbfield)的限制是,以同样的方式呈现给定类型的所有数据库字段,无论它是否应该是只读的。如果您的整个表单应该是只读的,那么这种方式是可行的,但是如果您处理的是一半只读一半不是的表单,最好依赖disabled 属性。

关于我的答案的更多细节:django modeladmin, readonly_fields and boolean fields

【讨论】:

这应该使用 disabled Field 属性,因为并非所有小部件都支持 (html) 属性(例如使用 django.contrib.gis.forms.fields.PointField),并且它可以由用户更改!所以应该使用form.base_fields[field_name].disabled = True 如果是相关字段(例如ForeignKey 字段),您可能需要删除添加/编辑/删除相关对象的小按钮。这可以通过设置适当的表单域小部件属性来完成,如here 所述。

以上是关于django admin如何在只读字段上显示小部件的主要内容,如果未能解决你的问题,请参考以下文章

Django Admin ForeignKey字段小部件选项和不一致的默认值

在 Django admin 中更改日期字段的默认小部件

Django:管理员:在管理员中更改字段的小部件

Django使用小部件创建一个只读的表单字段

如何在 django admin 上添加只读内联

如何使用django管理员多对多个字段选择器小部件