【问题标题】:How can I remove the add and change buttons from a TabularInline admin field?如何从 TabularInline 管理字段中删除添加和更改按钮?
【发布时间】:2018-03-05 21:25:25
【问题描述】:

我有模型 ABABA 对象有一个名为A.mManyToManyField,它可以通过我的中间模型AB 链接到许多B 对象。
我的A 模型的管理页面上有一个非常好的TabularInline 部分,其中包含AB 对象。

一切都好。除了TabularInline 部分在每个AB 对象的行中显示B 对象的“添加”和“更改”按钮,我想删除这些按钮。我仍然希望能够添加、更改和删除 AB 对象行,而不是它们引用的 B 对象。

我尝试将can_add_relatedcan_change_relatedcan_delete_related 属性设置为False,但这没有任何作用。

class ABInline(admin.TabularInline):
    model = AB
    def get_form(self, request, obj=None, **kwargs):
        form = super(ABInline, self).get_form(request, obj, **kwargs)
        form.base_fields['m'].widget.can_add_related = False
        form.base_fields['m'].widget.can_change_related = False
        form.base_fields['m'].widget.can_delete_related = False
        return form

这是一个错误吗?或者有没有其他方法可以为TabularInline 字段完成此操作?

【问题讨论】:

  • get_form 方法未在 TabularInline 上实现(onlyModelAdmin 上)。这就是为什么什么都没有发生。否则我认为它也不起作用,因为您需要更改AB 上指向B 的字段的小部件,而'm'A 上的字段。

标签: django django-admin


【解决方案1】:

你可以试试这个功能:

docs

class ABInline(admin.TabularInline):
    model = AB

    def has_add_permission(self, request):
      return False

    def has_change_permission(self, request, obj=None):
      return False

    def has_delete_permission(self, request, obj=None):
      return False

【讨论】:

  • 这没有回答问题:OP 说“我仍然希望能够添加、编辑和删除 AB 对象行,而不是它们引用的 B 对象。”这个答案影响 AB 对象,而不是 B 对象。反之亦然。
  • 如果has_change_permission 返回False,“添加”和“更改”按钮确实会消失,但仅适用于现有项目。它们仍可用于新的 (extra) 内联项目。此外,现有项目的选择框将变为“只读”。
【解决方案2】:

OP 设置小部件属性的想法应该可行。

基本思路如下:

TabularInline 中允许您选择B 对象的AB 中的实际表单字段是ModelChoiceField。该字段有一个Select 小部件,包裹在RelatedFieldWidgetWrapper 中。后者控制选择框旁边的“添加”和“更改”(或“编辑”)按钮。要删除这些按钮,请将小部件的 can_add_relatedcan_change_related 属性设置为 False

这实际上是 OP 试图做的。但是,OP 试图扩展 get_form,但据我所知,该方法仅适用于 ModelAdmin,而不适用于 TabularInline (source)。

我们可以扩展而不是使用get_form,例如formfield_for_dbfield (source) 在TabularInline 上,如下图所示(基于 OP 的示例):

class ABInline(admin.TabularInline):
    model = AB

    def formfield_for_dbfield(self, db_field, request, **kwargs):
        formfield = super(ABInline, self).formfield_for_dbfield(
            db_field, request, **kwargs)
        if db_field.name == 'b':
            # Assuming AB.b is the ForeignKey to B
            formfield.widget.can_add_related = False
            formfield.widget.can_change_related = False
            # formfield.widget.can_delete_related = False  # default is already False
        return formfield

这里我们假设 OP 的 AB 模型看起来像这样:

class AB(models.Model):
    a = models.ForeignKey(to='A', ...)
    b = models.ForeignKey(to='B', ...)
    ...

【讨论】:

  • 请注意,这在 formfield_for_dbfield() 中有效(或在 get_form() 中稍作修改),但它确实有效,例如在formfield_for_foreignkey() 中,因为formfield_for_dbfield() 将根据相关模型管理员的权限重置权限。见source
猜你喜欢
  • 2017-05-13
  • 1970-01-01
  • 2010-12-17
  • 2018-12-05
  • 1970-01-01
  • 2018-01-27
  • 2019-12-20
  • 1970-01-01
  • 2019-11-18
相关资源
最近更新 更多