How can I remove the add and change buttons from a TabularInline admin field?

China☆狼群 提交于 2021-01-02 07:48:54

问题


I have models A, B, and AB. A objects have a ManyToManyField called A.m that can link to many B objects, through my intermediary model AB.
I have a very nice TabularInline section full of AB objects, on my admin page for my A model.

All is well. Except that the TabularInline section shows "Add" and "Change" buttons for the B object in each AB object's row, and I want to remove those buttons. I still want to be able to add, change, and delete AB objects rows, just not the B objects they reference.

I have tried setting the can_add_related, can_change_related, can_delete_related attributes to False, but this does nothing.

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

Is this a bug? Or is there a different way to accomplish this for TabularInline fields?


回答1:


The OP's idea of setting the widget's attributes should work.

The basic idea is as follows:

The actual form field in the TabularInline for AB that allows you to select the B object is a ModelChoiceField. This field has a Select widget, wrapped in a RelatedFieldWidgetWrapper. The latter controls the "add" and "change" (or "edit") buttons next to the select box. To remove these buttons, set the widget's can_add_related and can_change_related attributes to False.

This is actually what the OP attempted to do. However, the OP tried to extend get_form, but that method is only available on a ModelAdmin, not on the TabularInline, as far as I know (source).

Instead of using get_form, we can extend e.g. formfield_for_dbfield (source) on the TabularInline, as illustrated below (based on OP's example):

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

Here we assume that the OP's AB model looks something like this:

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



回答2:


You could try with this functions:

See 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


来源:https://stackoverflow.com/questions/46396219/how-can-i-remove-the-add-and-change-buttons-from-a-tabularinline-admin-field

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!