[Solved]-Django admin: how to disable edit and delete link for foreignkey

15πŸ‘

βœ…

It’s not exactly a documented feature. Furthermore, formfield_for_dbfield is a damned mess (just as most of the django.contrib.admin). But it’s the cleanest approach I found, and it works fine for me.

class MyAdmin(django.contrib.admin.ModelAdmin):

    def formfield_for_dbfield(self, *args, **kwargs):
        formfield = super().formfield_for_dbfield(*args, **kwargs)

        formfield.widget.can_delete_related = False
        formfield.widget.can_change_related = False
        # formfield.widget.can_add_related = False  # can change this, too
        # formfield.widget.can_view_related = False  # can change this, too

        return formfield
πŸ‘€Art

9πŸ‘

in admin.py create a def under your model ModelAdmin class. Choose the options for Add, Change or Delete related to the foreign_key field, keeping the ones you desire to hide and deleting (or changing boolean from False to True) for the ones you wante to show:

class YourModelAdmin(admin.ModelAdmin):
    ...
    def get_form(self, request, obj=None, **kwargs):
        form = super(YourModelAdmin, self).get_form(request, obj, **kwargs)
        field = form.base_fields["your_foreign_key_field"]
        field.widget.can_add_related = False
        field.widget.can_change_related = False
        field.widget.can_delete_related = False
        return form
πŸ‘€Guaracy Lima

4πŸ‘

(Transferring my comment to an answer)

The above answers work great for regular admin pages. To get this to work in an admin inline (ex: admin.StackedInline), use get_formset instead of get_form:

def get_formset(self, request, obj=None, **kwargs):
     formset = super().get_formset(request, obj, **kwargs)
     field = formset.form.base_fields["your_foreign_key_field"]
     field.widget.can_add_related = False
     field.widget.can_change_related = False
     field.widget.can_delete_related = False
     return formset

πŸ‘€arielkaluzhny

3πŸ‘

Just to add to the completeness of Art’s answer:

For an Inline (admin.StackedInline, admin.TabularInline) you can use formfield_for_dbfield as well:

class MyInline(django.contrib.admin.TabularInline):

    def formfield_for_dbfield(self, *args, **kwargs):
        formfield = super().formfield_for_dbfield(*args, **kwargs)
        if formfield:
            formfield.widget.can_delete_related = False
            formfield.widget.can_change_related = False
            formfield.widget.can_add_related = False
            formfield.widget.can_view_related = False

        return formfield

formfield is somehow None sometimes for Inlines so you need to add the if statement.

πŸ‘€Austin Fox

0πŸ‘

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.fields['xxx'].widget.can_delete_related = False
πŸ‘€Mas Zero

Leave a comment