12

I've read about the can_add_related feature here: https://code.djangoproject.com/ticket/9071

I tried using it this way:

def get_form(self, request, obj=None, **kwargs):
    self.fields['person'].can_add_related = False
    return super(OperationAdmin, self).get_form(request, obj, **kwargs)

But this throws a TypeError and I don't know how to solve this.

Can someone point me in the right direction?

Thank you.

normic
  • 1,388
  • 3
  • 24
  • 36

5 Answers5

20

This is probably coming in late. But for other viewers reference,

def get_form(self, request, obj=None, **kwargs):
    form = super(ProductAdmin, self).get_form(request, obj, **kwargs)
    form.base_fields['category'].widget.can_add_related = False
    return form
Mo J. Mughrabi
  • 6,747
  • 16
  • 85
  • 143
  • 1
    for everyone who's trying that, this simply works, even with Django 1.7 - **but** not with Inlines. For them I ended up with overwriting the widgets, as explained by @Seether , see here: [link](http://stackoverflow.com/questions/26425818/django-1-7-removing-add-button-from-inline-form) – normic May 08 '15 at 16:37
  • 1
    See this answer to the question linked in @normic's comment for a much conciser solution for inlines (using get_formset instead of get_form) http://stackoverflow.com/a/37558444/1302095 – jenniwren Aug 30 '16 at 22:15
3

can_add_related seems to be an attribute on the widget, not the field, so try:

self.fields['person'].widget.can_add_related = False
Timmy O'Mahony
  • 53,000
  • 18
  • 155
  • 177
1

Alternative approach, with changing widget options *before* the form is instantiated:

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

    def formfield_for_dbfield(self, *args, **kwargs):
        formfield = super().formfield_for_dbfield(*args, **kwargs)
        if hasattr(formfield, "widget"):
            formfield.widget.can_add_related = False
            formfield.widget.can_delete_related = False
            formfield.widget.can_change_related = False
        else:
            pass  # this relation doesn't have an admin page to add/delete/change

        return formfield
Art
  • 2,235
  • 18
  • 34
1

Another approach, if you are defining an Inline model and use it in your admin, would be to overwrite the get_formset method:

from django.contrib import admin


class MyModelInline(admin.TabularInline):
    model = MyModel
    extra = 0
    min_num = 1
    max_num = 10
    fields = [
        'some_field'
    ]

    def get_formset(self, request, obj=None, **kwargs):
        fs = super().get_formset(request, obj, **kwargs)
        fs.form.base_fields['some_field'].widget.can_add_related = False
        fs.form.base_fields['some_field'].widget.can_change_related = False
        fs.form.base_fields['some_field'].widget.can_delete_related = False
        return fs
babis21
  • 1,515
  • 1
  • 16
  • 29
0

For TabularInline you can combine the answer from @Art and @babis21:

We can use the @Art answer here as well using the following:

    def get_formset(self, request, obj=None, **kwargs):
        res = super().get_formset(request, obj=None, **kwargs)
        for formfield in res.form.base_fields.values():
            if hasattr(formfield, "widget"):
                formfield.widget.can_add_related = False
                formfield.widget.can_delete_related = False
                formfield.widget.can_change_related = False
        return res
kholioeg
  • 326
  • 3
  • 5