3

as part of a form wizard I'm trying to pass an argument from the get_form_kwargs method within form wizard to my form, and then onto a modelformset. I've looked at numerous examples on SO (e.g. here, here and here)

The code looks ok to me (beginner), but it's still generating this error:

Exception Type: TypeError
Exception Value: __init__() got an unexpected keyword argument 'parent'

relevant views.py extract:

def get_form_kwargs(self, step=None):
        kwargs = {}
        if self.steps.current == 'assign_child':
            kwargs = super(checkout, self).get_form_kwargs(step)
            kwargs.update({
                'parent': self.request.user,
                })
            return kwargs

forms.py extract:

class bindBookingItems(ModelForm):
    class Meta:
        model = BookingItem
        fields = ('assignedKids',)
        widgets = {
                    'assignedKids': Select(attrs={'class': 'form-control',}),
            }
    def __init__(self, *args, **kwargs):
        parent = kwargs.pop('parent', None)
        super(bindBookingItems, self).__init__(*args, **kwargs)
        form.fields['assignedKids'].queryset = getChildren(parent.id)

checkout_bindBookingItemsFormSet = modelformset_factory(
        BookingItem, 
        form = bindBookingItems, 
        fields=('assignedKids', ),
        extra=0, max_num=5, can_delete=False)

My current thinking is that the problem lies somewhere in forms.py. The argument is obviously being picked up since it's complaining about it. However, I think i'm popping the kwarg correctly before the super statement.

What am I doing wrong?

Updated question with the fact that there's a modelformset in the mix. Apologies for omitting this information. Completely slipped my mind.

Updated with traceback:

Traceback:
File "D:\Python27\Lib\site-packages\django\core\handlers\base.py" in get_response
  111.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)
File "D:\Python27\Lib\site-packages\django\views\generic\base.py" in view
  69.             return self.dispatch(request, *args, **kwargs)
File "D:\Python27\Lib\site-packages\django\contrib\formtools\wizard\views.py" in dispatch
  237.         response = super(WizardView, self).dispatch(request, *args, **kwargs)
File "D:\Python27\Lib\site-packages\django\views\generic\base.py" in dispatch
  87.         return handler(request, *args, **kwargs)
File "D:\Python27\Lib\site-packages\django\contrib\formtools\wizard\views.py" in get
  255.         return self.render(self.get_form())
File "D:\Python27\Lib\site-packages\django\contrib\formtools\wizard\views.py" in get_form
  419.         return form_class(**kwargs)
File "D:\Python27\Lib\site-packages\django\forms\models.py" in __init__
  558.         super(BaseModelFormSet, self).__init__(**defaults)

Exception Type: TypeError at /checkout/
Exception Value: __init__() got an unexpected keyword argument 'parent'
Community
  • 1
  • 1
AndrewO
  • 1,105
  • 4
  • 16
  • 33
  • as per the answer [here](http://stackoverflow.com/a/18605865/3591273) the __init__ method does not expect a 'parent' kwargument but another one, try changing the (assigned) names of the arguments – Nikos M. Feb 13 '15 at 14:34
  • What happens if you try changing the method signature to `def __init__(self, parent=None, *args, **kwargs):` and directly using parent instead of popping it from kwargs? – Selcuk Feb 13 '15 at 14:55
  • @Selcuk - by modifying the method signature to `def __init__(self, parent=None, *args, **kwargs)` and removing the popping of kwargs i'm still getting the same error – AndrewO Feb 13 '15 at 15:01
  • You might be calling another `__init__`. Where are you exactly getting the error? Can you post stack trace? – Selcuk Feb 13 '15 at 15:02
  • @NikosM. - that particular article ([link](http://stackoverflow.com/a/18605865/763880) specifically talks about matched arguments, which I believe I'm already doing. i.e. the `__init__ ` method is using the same kwarg as what is being passed in the view. Have i understood your comment correctly? – AndrewO Feb 13 '15 at 15:04
  • @Selcuk - now updated with stacktrace – AndrewO Feb 13 '15 at 15:06
  • @Selcuk - i'm getting the error when requesting the URL with the form. Your comment about other __init__ locations has prompted me. This form is being put into a modelform_factory, which I'm assuming is going to have it's own way of handling the passed kwargs. I'm going to try the approach detailed here (http://stackoverflow.com/a/624013/763880) to see if this helps – AndrewO Feb 13 '15 at 15:26
  • @AndrewO, kwargs are **named arguments** so a named argument not expected will throw an error. This is what the link was saying. i think this is the issue here. – Nikos M. Feb 14 '15 at 12:47

1 Answers1

1

Here is a brilliant example illustrating how to correctly override get_form_kwargs.

I was very confused since I could not find a descent example in S.O. so far.

Assuming this form:

from django import forms

from .models import MyModel


class MyForm(forms.ModelForm):

    class Meta:
        model = MyModel

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

        # set the user_id as an attribute of the form
        self.user_id = user_id

Now that the form is defined, the view needs to inject the form with the user id:

from django.views.generic import UpdateView

# this assumes that django-braces is installed
from braces.views import LoginRequiredMixin

from .forms import MyForm
from .models import MyModel


class MyUpdateView(LoginRequiredMixin, UpdateView):
    model = MyModel
    form_class = MyForm
    success_url = "/someplace/"

    def get_form_kwargs(self):
        """This method is what injects forms with their keyword
            arguments."""
        # grab the current set of form #kwargs
        kwargs = super(MyUpdateView, self).get_form_kwargs()
        # Update the kwargs with the user_id
        kwargs['user_id'] = self.request.user.pk
        return kwargs
raratiru
  • 8,748
  • 4
  • 73
  • 113