This was fixed in Django 1.9 with form_kwargs.
I have a Django Form that looks like this:
class ServiceForm(forms.Form):
option = forms.ModelChoiceField(queryset=ServiceOption.objects.none())
rate = forms.DecimalField(widget=custom_widgets.SmallField())
units = forms.IntegerField(min_value=1, widget=custom_widgets.SmallField())
def __init__(self, *args, **kwargs):
affiliate = kwargs.pop('affiliate')
super(ServiceForm, self).__init__(*args, **kwargs)
self.fields["option"].queryset = ServiceOption.objects.filter(affiliate=affiliate)
I call this form with something like this:
form = ServiceForm(affiliate=request.affiliate)
Where request.affiliate
is the logged in user. This works as intended.
My problem is that I now want to turn this single form into a formset. What I can't figure out is how I can pass the affiliate information to the individual forms when creating the formset. According to the docs to make a formset out of this I need to do something like this:
ServiceFormSet = forms.formsets.formset_factory(ServiceForm, extra=3)
And then I need to create it like this:
formset = ServiceFormSet()
Now how can I pass affiliate=request.affiliate to the individual forms this way?
Official Document Way
Django 2.0:
https://docs.djangoproject.com/en/2.0/topics/forms/formsets/#passing-custom-parameters-to-formset-forms
As of commit e091c18f50266097f648efc7cac2503968e9d217 on Tue Aug 14 23:44:46 2012 +0200 the accepted solution can't work anymore.
The current version of django.forms.models.modelform_factory() function uses a "type construction technique", calling the type() function on the passed form to get the metaclass type, then using the result to construct a class-object of its type on the fly::
This means even a
curry
ed orpartial
object passed instead of a form "causes the duck to bite you" so to speak: it'll call a function with the construction parameters of aModelFormClass
object, returning the error message::To work around this I wrote a generator function that uses a closure to return a subclass of any class specified as first parameter, that then calls
super.__init__
afterupdate
ing the kwargs with the ones supplied on the generator function's call::Then in your code you'll call the form factory as::
caveats:
I'm a newbie here so I can't add comment. I hope this code will work too:
as for adding additional parameters to the formset's
BaseFormSet
instead of form.I like the closure solution for being "cleaner" and more Pythonic (so +1 to mmarshall answer) but Django forms also have a callback mechanism you can use for filtering querysets in formsets.
It's also not documented, which I think is an indicator the Django devs might not like it as much.
So you basically create your formset the same but add the callback:
This is creating an instance of a class that looks like this:
This should give you the general idea. It's a little more complex making the callback an object method like this, but gives you a little more flexibility as opposed to doing a simple function callback.
This is what worked for me, Django 1.7:
Hope it helps someone, took me long enough to figure it out ;)
Carl Meyer's solution looks very elegant. I tried implementing it for modelformsets. I was under the impression that I could not call staticmethods within a class, but the following inexplicably works:
In my view, if I do something like this:
Then the "request" keyword gets propagated to all of the member forms of my formset. I'm pleased, but I have no idea why this is working - it seems wrong. Any suggestions?