Django form __init__() got multiple values for keyword argument
Asked Answered
P

3

29

Hello, I'm trying to use a modified __init__ form method, but I am encountering the following error:

TypeError
__init__() got multiple values for keyword argument 'vUserProfile'

I need to pass UserProfile to my form, to get to dbname field, and I think this is a solution (my form code):

class ClienteForm(ModelForm):
class Meta:
    model = Cliente

def __init__(self, vUserProfile, *args, **kwargs):
    super(ClienteForm, self).__init__(*args, **kwargs)
    self.fields["idcidade"].queryset = Cidade.objects.using(vUserProfile.dbname).all()

Calls to constructor ClienteForm() without POST are successful and show me the correct form. But when the form is submitted and the constructor is called with POST, I get the previously described error.

Plexus answered 14/1, 2013 at 16:12 Comment(0)
H
51

You've changed the signature of the form's __init__ method so that vUserProfile is the first argument. But here:

formPessoa = ClienteForm(request.POST, instance=cliente, vUserProfile=profile)

you pass request.POST as the first argument - except that this will be interpreted as vUserProfile. And then you also try to pass vUserProfile as a keyword arg.

Really, you should avoid changing the method signature, and just get the new data from kwargs:

def __init__(self, *args, **kwargs):
    vUserProfile = kwargs.pop('vUserProfile', None)
Hochheimer answered 14/1, 2013 at 16:15 Comment(3)
Thanks very much! works fine now.. I stay signature is default.. and use your tip...Plexus
I have other problem now.. how can I pass this code to one inlineformset_factory ?Plexus
Great solution, thanks! Does anyone think there is a way to achieve the same without the kwargs trick? Imo it makes the init less user friendly, it would be great to be able to add explicit keyword arguments.Harlequinade
T
33

For the help of those others who Google to here: the error comes from init picking up the argument from both a positional argument and the default argument. Daniel Roseman's is accurate for the question as asked.

This can be either:

  1. You put the argument by position and then by keyword:

    class C():
      def __init__(self, arg): ...
    
    x = C(1, arg=2)   # you passed arg twice!  
    
  2. You forgot to put self as the first argument:

    class C():
       def __init__(arg):  ...
    
    x = C(arg=1)   # but a position argument (for self) is automatically 
                   # added by __new__()!
    
Tangerine answered 26/7, 2013 at 0:23 Comment(0)
M
2

I think this is the case with ModelForm, but need to check. For me, the solution was:

def __init__(self, *args, **kwargs):
    self.vUserProfile = kwargs.get('vUserProfile', None)
    del kwargs['vUserProfile']
    super(ClienteForm, self).__init__(*args, **kwargs)
    self.fields["idcidade"].queryset = Cidade.objects.using(self.vUserProfile.dbname).all()
Montford answered 15/12, 2013 at 23:53 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.