Passing Custom Form parameter to formset

2019-04-10 14:43发布

问题:

I have the following Form defined

class MyForm(ModelForm):  
    def __init__(self, readOnly=False, *args, **kwargs):  
      super(MyForm,self).__init__(*args,**kwrds)  
      if readOnly:  
        Do stuff to make the inputs readonly

MyForm works perfectly when I instantiate it in the view as a form
form = MyForm(readOnly=True, instance=ModelA)

but when I try to use it in the inlineformset_factory
Formset = inlineformset_factory(ModelA, ModelB form=MyForm(readOnly=True))
I get the error "NoneType object is not callable."

I think this is because the form is being initialised without a model instance
because MyForm is being initialised within the inline

I know the problem is the way I am using the MyForm in the inline call
because I get the same error if I do either of the following

Formset = inlineformset_factory(ModelA, ModelB form=MyForm(readOnly=True))
Formset = inlineformset_factory(ModelA, ModelB form=MyForm())

but it works if I do
Formset = inlineformset_factory(ModelA, ModelB form=MyForm)

obviously the readOnly param defaults to False and my inputs are not changed. Does anyone know how I can pass the readOnly param to MyForm using the inlineformset_factory or how else I can achieve what I want?

Thanks Andrew

回答1:

Digging through django.forms.models you can see that inlineformset_factory needs a form class, not an instance. This is why your last try works and the other fail...passing in an instance won't work.

This should give you what you are looking for:

class MyReadOnlyForm(MyForm):

    def __init__(self, *args, **kwargs):
        super(MyReadOnlyForm,self).__init__(readOnly=True, *args,**kwargs)


Formset = inlineformset_factory(ModelA, ModelB form=MyReadOnlyForm)

If you need both versions

if read_only is True:
    form_class = MyReadOnlyForm
else:
    form_class = MyForm 

Formset = inlineformset_factory(ModelA, ModelB form=form_class)


回答2:

Thanks. I did find the following in another post and was wondering if one was better than the other.

Formset = inlineformset_factory(ModelA, ModelB form=MyForm)
Formset.form = staticmethod(curry(MyForm, reaOnly=readOnlyvalue))
myFormset = Formset(request.Files, instance=modelAInst)