Django: disable inline option to add new referenced objects

Posted by ads' corner on Saturday, 2020-11-21
Posted in [Django][Python]

The Django Web Framework makes it quite easy to add new referenced objects in the admin menu.

Let’s say the model has two foreign keys in it:

1
2
3
class TeamMember(models.Model):
    team = models.ForeignKey(Team, on_delete=models.CASCADE, verbose_name=_("Team"))
    user = models.ForeignKey(CustomUser, on_delete=models.CASCADE, verbose_name=_("User"))

And the admin form:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
class TeamMemberForm(forms.ModelForm):
    class Meta:
        model = TeamMember

class CustomTeamMemberAdmin(admin.ModelAdmin):
    form = TeamMemberForm
    add_form = TeamMemberForm
    model = TeamMember
    fieldsets = [
        (None,      {'fields': ['team', 'user']}),
    ]

admin.site.register(TeamMember, CustomTeamMemberAdmin)

Then Django will show small a small green + sign next to the fields:

Add reference
Add reference

Add external reference
Add external reference

However that is not always desirable. In my use case I want a clear separation between changing teams, and changing team members. Note: this can’t be resolved with permissions (removing the permissions for one one model will remove the add option, but that’s not what I want - I still want permissions for both, just separate the actions).

Django makes it easy to remove the option to add new references inline in this form. In order to do that, the ModelAdmin must be extended by a get_form() function:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
class CustomTeamMemberAdmin(admin.ModelAdmin):
    form = TeamMemberForm
    add_form = TeamMemberForm
    model = TeamMember
    fieldsets = [
        (None,      {'fields': ['team', 'user']}),
    ]

    # disable green "+" buttons to add new objects in foreign table
    def get_form(self, request, obj=None, **kwargs):
        form = super(CustomTeamMemberAdmin, self).get_form(request, obj, **kwargs)
        form.base_fields['team'].widget.can_add_related = False
        form.base_fields['user'].widget.can_add_related = False
        return form

In this function, the widgets for the two fields have an extra can_add_related option set to False. That is enough to disable this option.

No plus reference
No plus reference

By the way: the same way the add new reference option can be disabled, it is also possible to disable the edit and delete options:

  • widget.can_change_related will disable the edit button
  • widget.can_delete_related will disable the delete button

Categories: [Django] [Python]
Tags: [Django] [Python] [Website]