Django: no ManagementForm data ... Formset will not be validated. What for?

For some reason, my form set will not be validated after submission. Any ideas on this could happen?

# models.py

class Department(models.Model): department = models.CharField(verbose_name = "Department Name", max_length=100) description = models.TextField(verbose_name = "Description", blank=True, null=True) sp_description = models.TextField(verbose_name = "Description (Spanish)", blank=True, null=True) phone = PhoneNumberField() phone_ext = models.CharField(max_length=10, blank=True) #Relations provider = models.ForeignKey(Provider, blank=True, null=True) services_offered = models.ManyToManyField(ServiceType) def __unicode__(self): return self.department 

# view.py

 def display_step5(request): msg = '' email = request.session.get('email') provider_obj = retrieve_provider_instance(email) AddDepartmentFormSet = inlineformset_factory(Provider, Department, extra=0) if is_authenticated(request): AddDepartmentFormSet = inlineformset_factory(Provider, Department, extra=0) if request.method=='POST': if 'add_department' in request.POST: cp = request.POST.copy() cp['department-TOTAL_FORMS'] = int(cp['department-TOTAL_FORMS'])+ 1 new_department = AddDepartmentFormSet(cp, prefix='department', instance=provider_obj) elif 'submit' in request.POST: formset = AddDepartmentFormSet(request.POST, instance=provider_obj) instances = formset.save(commit=False) for instance in instances: instance.provider = provider_obj instance.save() return HttpResponse("Departments have been added") else: new_department = AddDepartmentFormSet(prefix='department', instance=provider_obj) else: return HttpResponseRedirect(reverse('health.register.views.display_auth')) return render_to_response('step5-test.html', {'department': new_department}, context_instance=RequestContext(request)) 

step5-test.html

 <form method='post' action='{{request.path}}'>{% csrf_token %} <fieldset> <legend>Departments</legend> {{ department.management_form }} {% for form in department.forms %} <HR> <div><table>{{form.as_table}}</table></div> {% endfor %} <BR/> <input title='Add a new department' type='submit' name='add_department' value='Add-Another-Department' /> </fieldset> <BR/><BR/> <input title='Submit this form' type='submit' name='submit' value='Submit' /> </form> 

Following (solution):

The proposed Brant gave some insight into why the error occurred. For my case, his understanding helped me build a hack that worked best for my situation. This hack seems to be applicable for forms that can be modified in a certain way in a template. In my case, my form set became complicated and required some ajax to make it more user friendly.

"retrieve_provider_instance (email)" is a dynamic way to get a provider object based on various criteria set in the database (about 200 lines of code vomiting).

The next hack worked for me after some extensive debugging. I solved this by adding this hidden field to my "for" loop template

 {% {for form in formset.forms %} <tr> <td> {% if form.instance.pk %} <!--- if instance already exists on db ---> {{ form.DELETE }} <input type='hidden' name="department_set-{{ forloop.counter0 }}-id" id="id_department_set-{{ forloop.counter0 }}-id" value={{ form.instance.pk }} /> {% endif %} Name: <br/> {{ form.department}} <br/> Phone Number: <br/> {{ form.phone }} <br/> Phone Ext: <br/> {{ form.phone_ext }}</td> <td>Description: <br/> {{ form.description }}</td> <td>Description (Spanish): <br/> {{ form.sp_description }}</td> <td>Services Provided: <br/> {{ form.services_offered }}</td> <td></td> </tr> {% endfor %} 

I accepted Mark's answer because it was much more applicable to the specific question I asked. We hope this helps other users in the future who try to implement this example. In fact, assigning a β€œprefix” to submit is the correct way and makes the most sense.

Thanks for all your answers.

Regards Matt


Follow-up : I think I may have found some of my problem. But it has not yet been resolved.

The following is additional information that may help solve the problem. Could erroneous POST data ruin this? And if so, how do I get around this?

This is what happens after the form is submitted (in this case there is only one form):

Traceback is as follows:

File "/home/mhjohnson/webapps/resourcedb/lib/python2.6/django/forms/formsets.py" in _management_form 68. Raise ValidationError ("ManagementForm data is missing or was tampered with")

This is my POST data:

 department-0-phone_ext -----> u'222' department-0-id -----> u'' department-0-services_offered -----> u'2' department-0-phone -----> u'222-222-2222' department-INITIAL_FORMS -----> u'0' submit -----> u'Submit' department-MAX_NUM_FORMS -----> u'' department-0-department -----> u'Test 1' department-0-provider -----> u'' department-TOTAL_FORMS -----> u'1' csrfmiddlewaretoken -----> u'92a39322b16ed7e5e10dbd6c5ac64bf4' department-0-description -----> u'Blah blah' department-0-sp_description -----> u'....' 

Any ideas?

+4
source share
2 answers

Your problem is here:

  if request.method=='POST': if 'add_department' in request.POST: cp = request.POST.copy() cp['department-TOTAL_FORMS'] = int(cp['department-TOTAL_FORMS'])+ 1 new_department = AddDepartmentFormSet(cp, prefix='department', instance=provider_obj) elif 'submit' in request.POST: formset = AddDepartmentFormSet(request.POST, instance=provider_obj) instances = formset.save(commit=False) for instance in instances: instance.provider = provider_obj instance.save() return HttpResponse("Departments have been added") else: new_department = AddDepartmentFormSet(prefix='department', instance=provider_obj) 

If there is no POST, you pass the prefix 'department'. If "add_department" is in POST, you pass the prefix "department". However, when "submit" is in POST, you do not pass the prefix. Without a prefix, a form set cannot find the correct data in POST.

+5
source

Two things jump on me ...

First, you do not need to do this part:

 for instance in instances: instance.provider = provider_obj instance.save() 

This is taken care of when you do this:

 formset = AddDepartmentFormSet(request.POST, instance=provider_obj) 

Secondly, your code is at the top:

 provider_obj = retrieve_provider_instance(email) 

May not work. In the trace you provided, this is not like what the provider gets there ...

 department-0-provider -----> u'' 
+3
source

Source: https://habr.com/ru/post/1334811/


All Articles