views:

167

answers:

1

Hi,

I am trying to save a modelform that represents a bank account but I keep getting a ValueError even though the form appears to validate. The models I have to use are:

class Person(models.Model):
   name = models.CharField()


class Bank(models.Model):
    bsb = models.CharField()
    bank_name = models.CharField()  
    def __unicode__(self):
        return '%s - %s', (self.bank_name, self.bsb)
    def _get_list_item(self):
        return self.id, self
    list_item = property(-get_list_item)


class BankAccount(models.Model):
    bank = models.ForignKey(Bank)
    account_name = models.CharField()
    account_number = models.CharField()


class PersonBankAcc(models.Model):
    person = models.ForeignKey(Person)

The ModelForm for the personBankAcc;

def PersonBankAccForm(forms.ModelForm):
    bank = forms.ChoiceField(widget=SelectWithPop)
    class Meta:
        model = PersonBankAcct
        exclude = ['person']

    def __init__(self, *args, **kwargs):
        super(PersonBankAccForm, self).__init__(*args, **kwargs)
        bank_choices = [bank.list_item for banks in Bank.objects.all()]
        bank_choices.isert(0,('','------'))
        self.fields['bank'].choices = bank_choices

The view is:

def editPersonBankAcc(request, personBankAcc_id=0):
    personBankAcc = get_object_or_404(PersonBankAcc, pk=personBankAcc_id)
    if request.method == 'POST':
        form = PersonBankAccForm(request.POST, instance=personBankAcc )
        if form.is_valid():
            print 'form is valid'
            form.save()


         return HttpResponseRedirect('editPerson/' + personBankAcc.person.id +'/')
     else:
         form = PersonBankAccForm(instance=personBankAcc )
     return render_to_response('editPersonBankAcc', {'form': form})

When I try to save the form I get the a VlaueError exception even though it gets passed the form.is_valid() check, the error I get is:
Cannot assign "u'26'": PersonBankAcc.bank must be a "bank" instance

I know the issue is arising because of the widget I am using in the PersonBankAccForm:
bank = forms.ChoiceField(widget=SelectWithPop)
because if I remove it it works. But all that does is gives me the ability to add a new bank to the database via a popup and then inserts it into the select list, similar to the admin popup forms. I have checked the database and the new bank is added. But it fails even if I don't change anything, if I call the form and submit it, I get the same error.

I don't understand why it does not fail at the is_valid check.

Any help would be greatly appreciated.

Thanks
Andrew

+2  A: 

better yet, i don't think it really needs to be in the init function...

def PersonBankAccForm(forms.ModelForm):
    bank = forms.ModelChoiceField(queryset=Bank.objects.all(),widget=SelectWithPop(),empty_label='-----')
    class Meta:
        model = EmpBankAcct
        exclude = ['person']

    def __init__(self, *args, **kwargs):
        super(PersonBankAccForm, self).__init__(*args, **kwargs)
Brandon H
the reason is that your choice field is trying to save a string to a model that wants an object instance (of bank).
Brandon H
also, this might be an error from moving the example into this form, but your form init function says iit instead of init.
Brandon H
The iit is a typo in posting to the forum. When I remove the popup widget I leave the init function of the form as is and it still works. I tried what you suggested and I end up with an empty select list.
Andrew Gee
hmm. did you also change the ChoiceField to a ModelChoiceField?
Brandon H
i edited my answer. i don't think you need the init function, since you aren't really passing anything extra to it. the Bank.objects.all() queryset doesn't depend on anything passed to the modelform.
Brandon H
Excellent that did the trick. Thanks. I never new about the empty_label param, I can remove a bunch of code by using that.Thanks again.
Andrew Gee