Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing arguments to ModelForm through FormSet

I'm kinda new to Formsets and I'm stuck at a problem.

I use a Modelform to allow the creation of a new object.

class AddUpdateEntryForm(forms.ModelForm):

    class Meta:
        model = Zeit
        exclude = ('mitarbeiter', 'user_updated')

    def __init__(self, *args, **kwargs):
        self.user = kwargs.pop('user')
        super(AddUpdateEntryForm, self).__init__(*args, **kwargs)
        self.fields['projekt'].queryset = Projekt.objects.filter(firma=Mitarbeiter.objects.get(user_id=self.user).firma_id)

That form gets it's arguments from the view:

form = AddUpdateEntryForm(user=entry_user, initial=initial)

Now, I want to display multiple instances of that form on a single page. I use:

forms.py:
AddEntryFormSet = formset_factory(form=AddUpdateEntryForm)

and

views.py:
formset = AddEntryFormSet(initial=initial)

which works fine, but only when I comment out the "self.user...." and "self.fields...." lines from ModelForm Class.

I tried several ways of passing the argument from the call inside the view to the ModelForm. Is there a proper way to do this?

Thanks in advance Conrad

like image 847
Conrad Avatar asked Oct 03 '22 07:10

Conrad


1 Answers

It should be possible to subclass BaseModelFormset so that the user is passed to each form when it is constructed. However, that's quite tricky.

A simpler technique is to define a function that creates a model form for a given user, and dynamically create the model form class in the view.

def create_form(user):
    """Returns a new model form which uses the correct queryset for user"""

    class AddUpdateEntryForm(forms.ModelForm):

        class Meta:
            model = Zeit
            exclude = ('mitarbeiter', 'user_updated')

        def __init__(self, *args, **kwargs):
            super(AddUpdateEntryForm, self).__init__(*args, **kwargs)
            self.fields['projekt'].queryset = Projekt.objects.filter(firma=Mitarbeiter.objects.get(user_id=user).firma_id)

    return AddUpdateEntryForm

The closure of user in the function means that you can set the queryset correctly. Note that the __init__ method takes the same arguments as its parent class, so we no longer have any problems when we use modelformset_factory in the view.

AddUpdateEntryForm = create_form(user)
AddEntryFormSet = modelformset_factory(model=Zeit, form=AddUpdateEntryForm)
like image 197
Alasdair Avatar answered Oct 05 '22 15:10

Alasdair