views:

596

answers:

4

I can't running Unit Test with formset.

I try to do a test:

class NewClientTestCase(TestCase):

    def setUp(self):
        self.c = Client()

    def test_0_create_individual_with_same_adress(self):

        post_data =  {
            'ctype': User.CONTACT_INDIVIDUAL,
            'username': 'dupond.f',        
            'email': '[email protected]', 
            'password': 'pwd', 
            'password2': 'pwd', 
            'civility': User.CIVILITY_MISTER, 
            'first_name': 'François', 
            'last_name': 'DUPOND', 
            'phone': '+33 1 34 12 52 30', 
            'gsm': '+33 6 34 12 52 30', 
            'fax': '+33 1 34 12 52 30', 
            'form-0-address1': '33 avenue Gambetta', 
            'form-0-address2': 'apt 50', 
            'form-0-zip_code': '75020', 
            'form-0-city': 'Paris', 
            'form-0-country': 'FRA', 
            'same_for_billing': True,            
        }

        response = self.c.post(reverse('client:full_account'), post_data, follow=True)   

        self.assertRedirects(response, '%s?created=1' % reverse('client:dashboard'))

and i have this error:

ValidationError: [u'ManagementForm data is missing or has been tampered with']

My view :

    def full_account(request, url_redirect=''):    
        from forms import NewUserFullForm,  AddressForm,  BaseArticleFormSet

        fields_required = []
        fields_notrequired = []

        AddressFormSet = formset_factory(AddressForm, extra=2,  formset=BaseArticleFormSet)

        if request.method == 'POST':        
            form = NewUserFullForm(request.POST)        
            objforms = AddressFormSet(request.POST)            

            if objforms.is_valid() and form.is_valid():            
                user = form.save()            
                address = objforms.forms[0].save()


                if url_redirect=='':
                    url_redirect = '%s?created=1' % reverse('client:dashboard')
                    logon(request, form.instance)            
                return HttpResponseRedirect(url_redirect)
        else:
            form = NewUserFullForm()
            objforms = AddressFormSet()   

        return direct_to_template(request, 'clients/full_account.html', {
            'form':form,
            'formset': objforms, 
            'tld_fr':False, 
        })

and my form file :

class BaseArticleFormSet(BaseFormSet):

    def clean(self):        

        msg_err = _('Ce champ est obligatoire.')
        non_errors = True

        if 'same_for_billing' in self.data and self.data['same_for_billing'] == 'on':
            same_for_billing = True
        else:            
            same_for_billing = False

        for i in [0, 1]:

            form = self.forms[i]           

            for field in form.fields:                                
                name_field = 'form-%d-%s' % (i, field )
                value_field = self.data[name_field].strip()                

                if i == 0 and self.forms[0].fields[field].required and value_field =='':                    
                    form.errors[field] = msg_err                    
                    non_errors = False

                elif i == 1 and not same_for_billing and self.forms[1].fields[field].required and value_field =='':
                    form.errors[field] = msg_err                    
                    non_errors = False

        return non_errors

class AddressForm(forms.ModelForm):

    class Meta:
        model = Address

    address1 = forms.CharField()
    address2 = forms.CharField(required=False)
    zip_code = forms.CharField()
    city = forms.CharField()
    country = forms.ChoiceField(choices=CountryField.COUNTRIES,  initial='FRA')
+4  A: 

Every Django formset comes with a management form that needs to be included in the post. The official docs explain it pretty well. To use it within your unit test, you either need to write it out yourself. (The link I provided shows an example), or call formset.management_form which outputs the data.

Bartek
I added the contents of my files view and form
Py
Thanks a lot Bartek
Py
A: 

This doesn't seem to be a formset at all. Formsets will always have some sort of prefix on every POSTed value, as well as the ManagementForm that Bartek mentions. It might have helped if you posted the code of the view you're trying to test, and the form/formset it uses.

Daniel Roseman
I edited my question and added the contents of my files view and form
Py
I see you've updated the POST values so they do include the prefix - now the only thing missing is the management form data.
Daniel Roseman
+2  A: 

In particular, I've found that the ManagmentForm validator is looking for the following items to be POSTed:

form_data = {
            'form-TOTAL_FORMS': 1, 
            'form-INITIAL_FORMS': 0 
}
southgate
A: 

My case may be an outlier, but some instances were actually missing a fieldset in the stock "contrib" admin form/template leading to the error "ManagementForm data is missing or has been tampered with" when saved. The issue was with the unicode method (SomeModel: [Bad Unicode data]) which I found investigating the inlines that were missing.

The lesson learned is to not use the MS Charater Map, I guess. My issue was with vulgar fractions (¼, ½, ¾), but I'd assume it could occur many different ways. For special characters, copying/pasting from the w3 utf-8 page fixed it.

http://www.w3.org/2001/06/utf-8-test/postscript-utf-8.html

pragmar