# Formset validation

**URL:** <https://forum.djangoproject.com/t/formset-validation/3703>\
**Category:** Using Django\
**Created:** [August 1, 2020, 10:32am UTC](https://forum.djangoproject.com/t/formset-validation/3703 "2020-08-01T10:32:02Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![afekhaijoseph](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/afekhaijoseph/32/1709_2.png) [@afekhaijoseph](https://forum.djangoproject.com/u/afekhaijoseph)\
**Post date:** [August 1, 2020, 10:32am UTC](https://forum.djangoproject.com/t/formset-validation/3703/1 "2020-08-01T10:32:02Z")

</div>

Formsets have been driving me crazy for weeks because the documentation isn’t really helpful using them i keep getting a validation error every time i want to save a formset and i think i have everything in place.

Here is the traceback

```
            Traceback (most recent call last):
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/core/handlers/exception.py", line 34, in inner
                response = get_response(request)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/core/handlers/base.py", line 115, in _get_response
                response = self.process_exception_by_middleware(e, request)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/core/handlers/base.py", line 113, in _get_response
                response = wrapped_callback(request, *callback_args, **callback_kwargs)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/contrib/auth/decorators.py", line 21, in _wrapped_view
                return view_func(request, *args, **kwargs)
            File "/home/jojoe/portfolio_app/portfolioapp/portfolio/views.py", line 63, in portfolio_form
                if skillset.is_valid():
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/forms/formsets.py", line 308, in is_valid
                self.errors
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/forms/formsets.py", line 288, in errors
                self.full_clean()
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/forms/formsets.py", line 329, in full_clean
                for i in range(0, self.total_form_count()):
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/forms/formsets.py", line 112, in total_form_count
                return min(self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/utils/functional.py", line 48, in __get__
                res = instance. __dict__ [self.name] = self.func(instance)
            File "/home/jojoe/.local/lib/python3.8/site-packages/django/forms/formsets.py", line 92, in management_form
                raise ValidationError(
            django.core.exceptions.ValidationError: ['ManagementForm data is missing or has been tampered with']

```

**views**

```
            if request.method == 'POST':
                    print(request.POST)
                    person_form = PersonForm(request.POST, request.FILES)
                    occupation_form = OccupationForm(request.POST)
                    contact_form = ContactForm(request.POST)
                    skillset = SkillsFormSet(request.POST, prefix='skills')
                    workexpset = WorkExpFormSet(request.POST, prefix='work-exp')
                    acadexpset = AcadExpFormSet(request.POST, prefix='acad-exp')
                    

                # if person_form.is_valid() and occupation_form.is_valid() and skillset.is_valid() and workexpset.is_valid() and acadexpset.is_valid() and contact_form.is_valid():
                    if person_form.is_valid():
                        person=person_form.save(commit=False)
                        person.user=request.user
                        person.save()

                    if occupation_form.is_valid():
                        occupation=occupation_form.save(commit=False)
                        occupation.user=request.user
                        occupation.save()

                    if contact_form.is_valid():
                        contact=contact_form.save(commit=False)
                        contact.user=request.user
                        contact.save()

                    if skillset.is_valid():
                        instances = skillset.save(commit=false)
                        for instance in instances:
                            instance.user=request.user
                            instance.save()
                    if workexpset.is_valid():
                        instances = workexpset.save(commit=false)
                        for instance in instances:
                            instance.user=request.user
                            instance.save()
                    
                    if acadexpset.is_valid():
                        instances = acadexpset.save(commit=false)
                        for instance in instances:
                            instance.user=request.user
                            instance.save()

```

**template**

```
            <div>
                        {{skillset.management_form }}
                        {{skillset.non_form_errors}}
                        <div id="skill_set">
                            {% for skill in skillset %}
                            {{skill|crispy}}
                        {% endfor %}
                        </div>
                    <small style="display:none" id="alert-skill" class="alert alert-success">A skill has been added!</small>
                    <div id="empty_skill_form" style="display:none">
                        {{ skillset.empty_form }}  
                    </div>
                        <button id="addskill">add</button>
                    </div>

```

the other templates are the same so i don’t feel there is need for that

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 1, 2020, 1:26pm UTC](https://forum.djangoproject.com/t/formset-validation/3703/2 "2020-08-01T13:26:10Z")

</div>

Do you have any JavaScript that is modifying the form? If so, we’ll need to see that.

Any time you change the number of forms in a form set, you need to update the management form. See [https://docs.djangoproject.com/en/3.0/topics/forms/formsets/#understanding-the-managementform](https://docs.djangoproject.com/en/3.0/topics/forms/formsets/#understanding-the-managementform)

```
 If you are adding new forms via JavaScript, you should increment the count fields in this form as well.

```

Also, if you included the empty form _in_ the `<form>`, that might also do it. The empty form should be in a completely separate section.

---

<div class="post-metadata">

**Author:** ![afekhaijoseph](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/afekhaijoseph/32/1709_2.png) [@afekhaijoseph](https://forum.djangoproject.com/u/afekhaijoseph)\
**Post date:** [August 1, 2020, 2:19pm UTC](https://forum.djangoproject.com/t/formset-validation/3703/3 "2020-08-01T14:19:23Z")

</div>

yea i increment the count fields using jquery.

```
    $('#addworkexp').click(function(e) {
        e.preventDefault();
        console.log('clicked work')
        var workexp_idx = $('#id_workexp-TOTAL_FORMS').val();
        $('#workexp_set').append($('#empty_workexp_form').html().replace(/workexp- __prefix__ /g, workexp_idx));
        $('#id_workexp-TOTAL_FORMS').val(parseInt(workexp_idx) + 1);
        $('#alert-workexp').fadeIn("fast", function(){
          $(this).delay(1000).fadeOut("slow");
        });
      });

```

when you say "a completely different section do you mean outside the `<form>`?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 1, 2020, 2:36pm UTC](https://forum.djangoproject.com/t/formset-validation/3703/4 "2020-08-01T14:36:52Z")

</div>

Yes - you don’t want your blank-form template submitted as part of the form.

So what you want to check is that the right number of forms is being submitted to match what’s in the management form. (You can use the network tab of your browser developer tools to see what’s being submitted and verify it visually.)

If you run into any questions about understanding what’s being submitted, go ahead and post the response data here and we can walk through it.

---

<div class="post-metadata">

**Author:** ![afekhaijoseph](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/afekhaijoseph/32/1709_2.png) [@afekhaijoseph](https://forum.djangoproject.com/u/afekhaijoseph)\
**Post date:** [August 1, 2020, 3:50pm UTC](https://forum.djangoproject.com/t/formset-validation/3703/5 "2020-08-01T15:50:43Z")

</div>

So like you said the empty forms were submitting extra empty data so i took the outside the form and that’s fixed but the error still remains the same and so far the only area of the developer tools i am used to is the console since i’m pretty new to django. But here is the data being send.

```
            first_name	'john'  
            last_name 'doe'
            display_picture	''
            occupation 'software developer'
            skill-TOTAL_FORMS '1'
            skill-INITIAL_FORMS	'0'
            skill-MIN_NUM_FORMS '0'
            skill-MAX_NUM_FORMS	1000'
            skill-0-skills	'django'
            skill-0-id ''
            workexp-TOTAL_FORMS '2'
            workexp-INITIAL_FORMS '0'
            workexp-MIN_NUM_FORMS '0'
            workexp-MAX_NUM_FORMS '1000'
            workexp-0-company 'andela'
            workexp-0-started	'2015'
            workexp-0-left '2017'
            workexp-0-position 'intern'
            workexp-0-id ''
            1-company 'paystack'
            1-started '2017'
            1-left '2018'
            1-position	'junior developer'
            1-id ''
            acadexp-TOTAL_FORMS '1'
            acadexp-INITIAL_FORMS '0'
            acadexp-MIN_NUM_FORMS '0'
            acadexp-MAX_NUM_FORMS '1000'
            acadexp-0-education 'self taught'
            acadexp-0-id ''
            cell	
            '6669994444'
            twitter 'johndoe'
            instagram 'doejohn'
            linkedin	'john though'

```

is this the information you requested?

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 1, 2020, 3:56pm UTC](https://forum.djangoproject.com/t/formset-validation/3703/6 "2020-08-01T15:56:31Z")

</div>

It’s close enough - if you look at the workexp form, you can see that for form 0, you’re submitting entries like workexp-0-company. But for form 1, you’re submitting 1-company. You’ve dropped the workexp prefix from the form entry.

---

<div class="post-metadata">

**Author:** ![afekhaijoseph](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/afekhaijoseph/32/1709_2.png) [@afekhaijoseph](https://forum.djangoproject.com/u/afekhaijoseph)\
**Post date:** [August 2, 2020, 6:37am UTC](https://forum.djangoproject.com/t/formset-validation/3703/7 "2020-08-02T06:37:13Z")

</div>

Yes I see that now…but it still doesn’t fix the error

---

<div class="post-metadata">

**Author:** ![KenWhitesell](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/kenwhitesell/32/280_2.png) [@KenWhitesell](https://forum.djangoproject.com/u/KenWhitesell)\
**Post date:** [August 2, 2020, 12:33pm UTC](https://forum.djangoproject.com/t/formset-validation/3703/8 "2020-08-02T12:33:42Z")

</div>

Ok, so as the saying goes, we rinse and repeat this process.

Ah, I also just noticed that in the portion of the views.py file you posted, you have `prefix='skills'`, `prefix='work-exp'`, and `prefix='acad-exp'`, but the data being supplied you show prefixes of `skill`, `workexp`, and `acadexp`. You didn’t post the `GET` portion of your view, so I can’t compare them to verify an inconsistency.

Make sure you’re using the same prefixes as appropriate.

If you’re still running into problems after this, please post your complete view, your updated JavaScript and template, and the most current stack trace you’re receiving.

---

<div class="post-metadata">

**Author:** ![afekhaijoseph](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/afekhaijoseph/32/1709_2.png) [@afekhaijoseph](https://forum.djangoproject.com/u/afekhaijoseph)\
**Post date:** [August 2, 2020, 3:34pm UTC](https://forum.djangoproject.com/t/formset-validation/3703/9 "2020-08-02T15:34:30Z")

</div>

Ah, this!..this was the problem prefixes were different for the get and post request. Thank you once again for your help.

---

<div class="post-metadata">

**Author:** ![afekhaijoseph](https://sea2.discourse-cdn.com/flex026/user_avatar/forum.djangoproject.com/afekhaijoseph/32/1709_2.png) [@afekhaijoseph](https://forum.djangoproject.com/u/afekhaijoseph)\
**Post date:** [August 3, 2020, 7:44am UTC](https://forum.djangoproject.com/t/formset-validation/3703/10 "2020-08-03T07:44:01Z")

</div>

so i checked the database and it turns out only the data for the first form was saved. Didn’t realize it till i was trying to fix something else
