Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass an extra argument to django admin custom form?

As you know we can define a ModelForm and then replace add and change forms by setting form attribute in modelAdmin class. for example:

class FooAdminForm(django.forms.ModelForm):
     class Meta:
         model = Foo

     def __init__(self, *args, **kwargs):
         super(FooAdminForm, self).__init__(self, *args, **kwargs)


class FooAdmin(admin.ModelAdmin):
    form = FooAdminForm

in a simple view we can initialize a form object and pass extra arguments to init function of the form. something like this:

def my_view(request):
    form = FooAdminForm(p1='aaa', p2='bbb')

and then in the init function we can access these parameter.

self.p1 = kwargs.pop('p1')
self.p2 = kwargs.pop('p2')

but how can I pass arguments to modelAdmin form? I can only pass form class to modelAdmin form attribute, and I can't initialize it like in views.

I found a solution on stackoverflow here:

Use a form with a custom __init__ in Django Admin

but it adds a dynamic attribute to form object, which I think is a little hackish. Is there a better or formal way for doing this?

like image 580
Feanor Avatar asked Aug 07 '16 06:08

Feanor


1 Answers

I was looking around for a solution to this, and found a kinda-elegant solution in Django's issue tracker:

def get_form(self, request, obj=None, **kwargs):
    Form = super().get_form(request, obj=None, **kwargs)
    return functools.partial(Form, user=request.user)

https://code.djangoproject.com/ticket/27240#comment:9

So if you're using a custom form, you can simply pass it to super().get_form() using kwargs

def get_form(self, request, obj=None, **kwargs):
    kwargs['form'] = FooAdminForm
    Form = super().get_form(request, obj=None, **kwargs)
    return functools.partial(Form, user=request.user)
like image 88
radoh Avatar answered Oct 21 '22 04:10

radoh