0

I have a view which displays a form and saves the same form. When first showing the view I have no errors. However, when saving (POSTing) to the view I get the following error:

TypeError at /test6/settings/ int() argument must be a string or a number, not 'QueryDict'

View

@login_required
def keyword_settings(request, keyword):
    keyword = Keyword.objects.get(keyword=keyword, status="Active")

    # If we had a POST then get the request post values.
    if request.method == 'POST':
    # Populate the form with the instance.
        form = KeywordFrom(request.POST, instance=keyword)
        # Check we have valid data before saving trying to save.
        if form.is_valid():
            form.save()

    form = KeywordFrom(instance=keyword, user=request.user)
    context = {'form': form}
    return render_to_response('sms/keyword_settings.html', context, context_instance=RequestContext(request))

Form

class KeywordFrom(forms.ModelForm):

    def __init__(self, user=None, *args, **kwargs):
        """
        Init method.
        """
        super(KeywordFrom, self).__init__(*args, **kwargs)
        if user is not None:
            this_originator_name = Originator.objects.for_user(user)
            self.fields['sender_name'] = forms.ModelChoiceField(queryset=this_originator_name)

    class Meta:
        model = Keyword

I know the issue is with the sender_name but I have tried different things with no resolve.

GrantU
  • 6,325
  • 16
  • 59
  • 89

1 Answers1

7

Look at how you've overridden the __init__ method of your form:

def __init__(self, user=None, *args, **kwargs):

So the first explicit parameter (after the implicit self) is user.

Now look at how you're instantiating the form in the POST block:

form = KeywordFrom(request.POST, instance=keyword)

So the first parameter you're passing is the POST. But the form is expecting user in that position, and will put whatever you pass there into that variable.

You need to pass the user in when you instantiate on POST, which will fix the problem. But this indicates why it's a bad idea to mess around with the default signature of a class. You should really preserve the signature and take the user from kwargs:

def __init__(self, *args, **kwargs):
    user = kwargs.pop('user', None)
    super(KeywordFrom, self).__init__(*args, **kwargs)
    ...etc...
Daniel Roseman
  • 588,541
  • 66
  • 880
  • 895
  • I assumed this was the issue, all the examples I have looked at never suggested it was a bad idea tho ;) Thanks for the info I understand the concept now clearly from your answer. – GrantU Jul 16 '13 at 08:47