Note that there are some explanatory texts on larger screens.

plurals
  1. PODjango FormWizard dynamic forms
    primarykey
    data
    text
    <p>I am trying to create a FormWizard to add multiple instances of a model at once. The second page is dynamic, based on the number to be added, and creates a single "serial number" field - the differentiating factor between all the instances. </p> <p>I'm getting the first page of the wizard fine, but the second page - the dynamic one - is giving me this Validation Error: </p> <blockquote> <p>[u'ManagementForm data is missing or has been tampered.']</p> </blockquote> <p>All the searching I've done points to a formset issue, which I'm not using. What have I done wrong?</p> <p><strong>forms.py</strong></p> <pre><code>class CarrierWizardForm1(forms.Form): part_numbers = forms.ModelChoiceField(queryset=PartNumber.objects.all()) expiry_date = forms.DateField() qty_at_new = forms.IntegerField() unit_cost = forms.DecimalField(max_digits=10, min_value=0, decimal_places=3) cost_currency = forms.ChoiceField(choices=CURRENCY_CHOICES) class CarrierWizardForm2(forms.Form): def __init__(self, *args, **kwargs): qty = kwargs.pop('qty') super(CarrierWizardForm2,self).__init__(*args,**kwargs) for i in qty: self.fields['serial_%s' % i] = forms.CharField(max_length=45) </code></pre> <p>The defs in CarrierWizardForm2 is a fairly common idiom that is noted all over the web as a solution to this problem, including by <a href="http://jacobian.org/writing/dynamic-form-generation/" rel="nofollow">Jacobian</a> Nor is their anything crazy in urls</p> <p><strong>urls.py</strong> </p> <pre><code>carrier_wizard_forms = [CarrierWizardForm1, CarrierWizardForm2] ... url(r'^carrier/add/$', views.CarrierCreateWizard.as_view(carrier_wizard_forms)), </code></pre> <p>My views are relatively complex, but nothing outrageous. Note there are some fields that aren't in the forms - they are filled with context data (user, creation date, etc)</p> <p><strong>views.py</strong> </p> <pre><code>TEMPLATES = {"0": "inventory/carrier_wizard_form1.html", "1": "inventory/carrier_wizard_form2.html"} class CarrierCreateWizard(SessionWizardView): def get_template_names(self): return [TEMPLATES[self.steps.current]] ''' Get the qty from form 1 to indicate how many fields form2 needs for serial numbers ''' def get_form_initial(self, step): current_step = self.storage.current_step if current_step == 'step1': prev_data = self.storage.get_step_data('step0') return self.initial_dict.get(step, {'qty': qty}) return self.initial_dict.get(step, {}) def done(self, form_list, **kwargs): details = form_list[0] list_of_serial_nos = form_list[1] for serial_name, serial in list_of_serial_nos.cleaned_data.items(): carrier = Carrier() carrier.part_numbers = details.cleaned_data['part_numbers'] carrier.creation_date = datetime.datetime.today() carrier.expiry_date = details.cleaned_data['expiry_date'] carrier.qty_at_new = 1 carrier.qty_current = 1 carrier.serial = serial carrier.unit_cost = details.cleaned_data['unit_cost'] carrier.cost_currency = details.cleaned_data['cost_currency'] carrier.user = self.request.user carrier.save() </code></pre> <p>My second template is bland, although you can see three unsuccessful attempts to rectify this issue.</p> <p><strong>inventory/carrier_wizard_form2.html</strong></p> <pre><code>{% extends "base.html" %} {% block content %} &lt;p&gt;Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}&lt;/p&gt; &lt;form action="" method="post"&gt;{% csrf_token %} {# Attempt 3 #} {{ formset }} {# Attempt 2 {{ form.management_form }} {% for f in form %} {{ f.as_p }} {% endfor %} #} {# Attempt 1 {{ form }} #} &lt;input type=submit&gt; &lt;/form&gt; {% endblock %} </code></pre> <p><strong>EDIT</strong> *<em>As requested, both of my templates</em>*</p> <p>inventory/carrier_wizard_form1.html</p> <pre><code>{% extends "base.html" %} {% block content %} &lt;p&gt;Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}&lt;/p&gt; &lt;form action="" method="post"&gt;{% csrf_token %} {{ wizard.form.as_p }} &lt;input type=submit&gt; &lt;/form&gt; {% endblock %} </code></pre> <p>templates/inventory/carrier_wizard_form2.html</p> <pre><code>{% extends "base.html" %} {% block content %} &lt;p&gt;Step {{ wizard.steps.step1 }} of {{ wizard.steps.count }}&lt;/p&gt; &lt;form action="" method="post"&gt;{% csrf_token %} &lt;table&gt; {{ wizard.form }} {# {{ wizard.management_form }} {% if wizard.form.forms %}.. {{ wizard.form.management_form }} {% for form in wizard.form.forms %} {{ form }} {% endfor %} {% else %} {{ wizard.form }}. {% endif %} #} &lt;/table&gt; &lt;input type=submit&gt; &lt;/form&gt; {% endblock %} </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload