0

In my Django project i use 3 forms on one view. 2 of this forms is formsets. There is how looks like my forms:

class HotelForm(forms.Form):
        country = forms.CharField(label=(u'Select Country'))
        city = forms.CharField(label=(u'Select City'))
        hotel = forms.ChoiceField(label=(u'Hotel Stars'))
        from_date = forms.CharField(label=(u'Date from'))
        to_date = forms.CharField(label=(u'Date to'))
        rooms = forms.IntegerField(label=(u'Rooms'), min_value=1)
        food = forms.ChoiceField(label=(u'Food'),
                widget = forms.Select, choices = FOOD_CHOICES)

class TouristsForm(forms.Form):
        adult = forms.IntegerField(min_value=1, initial=1)
        children = forms.IntegerField(label=(min_value=0, initial=0, required=False)

class ChildrenAgeForm(forms.Form):
        children_age = forms.IntegerField(min_value=2, max_value=10, initial=2, required=False)

Depending on numbers of field rooms of HotelForm i add formset TouristsFormSet using js:

$('#id_booking_form-rooms').on('change', function(e){
   var n = $('#id_booking_form-rooms').val() || 0;
   var html = "";

   for (var i = 0; i < n; i++) {
      html += "<input id='id_tourists-TOTAL_FORMS' type='hidden' value='1' name='tourists-TOTAL_FORMS'>"
      + "<input id='id_tourists-INITIAL_FORMS' type='hidden' name='tourists-INITIAL_FORMS'>"
      + "<input id='id_tourists-MIN_NUM_FORMS' type='hidden' name='tourists-MIN_NUM_FORMS'>"
      + "<input id='id_tourists-MAX_NUM_FORMS' type='hidden' name='tourists-MAX_NUM_FORMS'>"
      + "<div>Quantity of people in the room " + (i + 1) + "</div>"
      + "<br/><label for='id_tourists-" + i + "-adult'>Adults quantity:</label>"
      + "<input id='id_tourists-" + i + "-adult' type='number' name='tourists-" + i + "-adult' value='0'/>"
      + "<label for='id_tourists-" + i + "-children'>Children quantity:</label>"
      + "<input id='id_tourists-" + i + "-children' type='number' name='tourists-" + i + "-children' class='children_age' value='0'/>"
      + "<div class='extrafieldWrapperChAge'></div>";
      }
      $(".extrafieldWrapper").html(html);
});

Depending on number of children of formset TouristsFormSet i add formset ChildrenAgeFormSet using js:

$(".extrafieldWrapper").on('change', '.children_age', function(e){
   var n = $(this).val() || 0;
   var html = "";
   for (var i = 0; i < n; i++) {
      html += "<input id='id_childrenage-TOTAL_FORMS' type='hidden' value='1' name='childrenage-TOTAL_FORMS'>"
      + "<input id='id_childrenage-INITIAL_FORMS' type='hidden' name='childrenage-INITIAL_FORMS'>"
      + "<input id='id_childrenage-MIN_NUM_FORMS' type='hidden' name='childrenage-MIN_NUM_FORMS'>"
      + "<input id='id_childrenage-MAX_NUM_FORMS' type='hidden' name='childrenage-MAX_NUM_FORMS'>"
      + "<br/><label for='id_childrenage-" + i + "-children_age'>Children Age "+(i+1)+"</label>"
      + "<input id='id_childrenage-" + i + "-children_age' type='number' value='0' name='childrenage-" + i + "children_age' />";
      }
$(this).next('.extrafieldWrapperChAge').html(html);
});

There is how looks like my html file:

<div class="large-6 columns">
   <div class="fieldWrapper">
     {% if booking_form.city.errors %}
       <ol style="list-style-type:square" >
         {% for error in booking_form.city.errors %}
           <li><strong>This field is required</strong></li>
         {% endfor %}
        </ol>
      {% endif %}
      {{ booking_form.city.label_tag }}
      {{ booking_form.city }}
     </div>
 </div>
 <!-- and other HotelForm fields -->
 <div class="extrafieldWrapper">
 <!-- here is load formset fields -->
 </div>
 <div class="row">
   <input type="submit" value="Find">
 </div>

and there is looks like my view:

def post(self, request, *args, **kwargs):
  TouristsFormSet = formset_factory(TouristsForm, extra = 1, max_num = 15)
  ChildrenAgeFormSet = formset_factory(ChildrenAgeForm, extra = 1, max_num = 20)
  booking_form = HotelForm(request.POST, prefix='booking_form')
  tourists_formset = TouristsFormSet(request.POST, prefix='tourists')
  childrenage_formset = ChildrenAgeFormSet(request.POST, prefix='childrenage')
  if booking_form.is_valid() and tourists_formset.is_valid() and childrenage_formset.is_valid():
    ...

Everything work fine, but if i leave adult, children fields of TouristsFormSet and/or children age fields of ChildrenAgeFormSet with default value, i receive error ValidationError at /booking/, [u'ManagementForm data is missing or has been tampered with'].

I tried to compare html code in browser when i use js and without js just using {{tourists_formset}} and {{childrenage_formset}}. And its seems to me that its the same . When i use formsets without js everything works fine

Also in traceback i find this line return min(self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max) when value of field children is 0 and _('ManagementForm data is missing or has been tampered with'), code='missing_management_form',

I will be thankful if somebody will help me with it.

Zagorodniy Olexiy
  • 2,132
  • 3
  • 22
  • 47
  • Possible duplicate of [Django ManagementForm data is missing or has been tampered with](http://stackoverflow.com/questions/12877576/django-managementform-data-is-missing-or-has-been-tampered-with) – rnevius Mar 09 '16 at 16:03
  • The management form should be added once for each formset. It looks as if you are adding it once for each form. I'm also not sure why you are hardcoding `value='1'`, if the total number of forms might change. – Alasdair Mar 09 '16 at 16:37
  • You might find it easier to debug if you get your forms working without javascript first. Then once that's working, you can fix your javascript so that it generates the required html. – Alasdair Mar 09 '16 at 16:37
  • @Alasdair Thank you for your comment. I tried to test forms with and without js. Without js everything works fine, i tried to compare to html and didn't find differences http://i.imgur.com/5OnRFt0.jpg?1 – Zagorodniy Olexiy Mar 10 '16 at 06:53
  • In traceback i see this line `return min(self.management_form.cleaned_data[TOTAL_FORM_COUNT], self.absolute_max)` when value of field `children ` is 0 and ` _('ManagementForm data is missing or has been tampered with'), code='missing_management_form',` – Zagorodniy Olexiy Mar 10 '16 at 07:25
  • As I said a couple of days ago: The management form should be added once for each formset. It looks as if you are adding it once for each form. I'm also not sure why you are hardcoding value='1', if the total number of forms might change. – Alasdair Mar 12 '16 at 14:12
  • I'm sorry for duplicating, i'm already update my previous post. I'm duplicate `value='1'` to make code the same as without js. In original i have no this value in my code – Zagorodniy Olexiy Mar 12 '16 at 14:15
  • Here's another idea to debug. Compare `request.POST` without JavaScript (when it works) and with JavaScript (when you get the error). What is the difference? – Alasdair Mar 12 '16 at 14:25
  • @Alasdair i'm sorry i didn't see that you said that management form should be added once for each formset. you was absolutely wright, you can make answer – Zagorodniy Olexiy Mar 12 '16 at 14:25
  • Great, glad you fixed the problem :) – Alasdair Mar 12 '16 at 14:33
  • Thank you very much. And sorry once again) – Zagorodniy Olexiy Mar 12 '16 at 14:34

1 Answers1

1

The management form should be added once for each formset. In your JavaScript, it looks as if you are adding it once for each form.

Alasdair
  • 298,606
  • 55
  • 578
  • 516