python template Il formset di Django solleva KeyError `form-0-id`



form html django (1)

Penso che devi chiamare is_valid prima di salvare il formset, anche se sei sicuro al 100% che i moduli siano validi:

if modelformset.is_valid():
    modelformset.save()

Sto cercando di salvare un formset ma continuo a ricevere

list_ = super(MultiValueDict, self).__getitem__(key)
KeyError: 'form-0-id'

During handling of the above exception, another exception occurred:
...
django.utils.datastructures.MultiValueDictKeyError: "'form-0-id'"

modelformset.forms solleva lo stesso errore.

Ecco una domanda che sembra molto vicina, ma l'aggiunta di {{form.id}} prima di {%for field in form.visible_fields %} non sembra essere di aiuto.

Esiste un campo id generato automaticamente nella tabella del database, ma non specificato esplicitamente nel modello (non è sicuro se sia pertinente). id non appare in alcun codice di moduli, campi o codice modello. id è solo una colonna del database generata automaticamente dalla migrate .

Ecco la vista che pubblico a:

views.py

def list_page(request, list_id):

    image_path = get_image_path(list_id)

    ordered_men = OrderedTable.objects.filter(list_id=list_id)
    ordered_men = list(enumerate(
        sorted(ordered_men, key=str)
    ))
    print(f'there are {len(ordered_men)} men')
    OrderedManInputFormSet = modelformset_factory(
        OrderedManInput,
        fields=fields,
        form=OrderedManInputForm, extra=0)

    ordered_man_input_formset = OrderedManInputFormSet(
        form_kwargs={
            'choices': ordered_men,
        }
    )

    return render(
        request, 'collector/list.html',
        {
            'list_id': list_id,
            'image_path': image_path,
            'formset': ordered_man_input_formset,
        }
    )


def submit(request, list_id):

    OrderedManInputFormSet = modelformset_factory(
        OrderedManInput,
        form=OrderedManInputForm,
        fields=fields,
        extra=0,
    )
    modelformset = OrderedManInputFormSet(request.POST)

    print('testing validity')
    if modelformset.is_valid():
        print('saving')
        modelformset.save()

    return HttpResponseRedirect(
        reverse('collector:thanks')
    )


def thanks(request):
    return render(request, 'collector/thanks.html')

forms.py

class OrderedManInputForm(forms.ModelForm):

    def __init__(self, *args, **kwargs):

        super(OrderedManInputForm, self).__init__(args, kwargs)
        if 'choices'in kwargs:
            # This works
            self.fields['full_name'] = forms.ChoiceField(
                choices=[('', '     ')] + kwargs['choices'],
                required=False
            )

    class Meta:
        model = OrderedManInput
        widgets = {}
        text_fields = [
            ...
        ]
        boolean_fields = [
            ...
        ]
        widgets.update({
            field: forms.TextInput()
            for field in text_fields
        })
        widgets.update({
            field: forms.CheckboxInput()
            for field in boolean_fields
        })
        fields = text_fields + boolean_fields
        labels = {
            ...
        }

Ecco il modello che fa la pubblicazione:

    <form action="{% url 'collector:submit' list_id %}" method="POST" enctype="multipart/form-data">
      {% csrf_token %}
      {{ formset.management_form }}

      <table id="id_data_table">
        {% for form in formset %}
           {{form.id}}
        {% if forloop.first %}
          <thead><tr>
            {% for field in form.visible_fields %}
              <th>{{ field.label|capfirst }}</th>
            {% endfor %}
          </tr></thead>
        {% endif %}
        <tr>
          {%for field in form.visible_fields %}
            <td>
              {{field}}
            </td>
          {%endfor%}
        </tr>
      {% endfor %}
    </table>
    <p/>
    <div class="div-submit">
          <input type="submit"/>
    </div>
  </form>

quindi ogni riga è una forma e ogni colonna un campo:

rintracciare:

[03/Sep/2017 00:08:21] "GET /collector/183618 HTTP/1.1" 200 20455
[03/Sep/2017 00:08:21] "GET /static/style.css HTTP/1.1" 200 1123
[03/Sep/2017 00:08:21] "GET /static/admin/js/vendor/jquery/jquery.js HTTP/1.1" 200 258648
[03/Sep/2017 00:08:21] "GET /static/lists_of_men_cropped/41550_1821100522_1170-01047.jpg HTTP/1.1" 404 1769
[03/Sep/2017 00:08:21] "GET /static/lists_of_men_cropped/41550_1821100522_1170-01047.jpg HTTP/1.1" 404 1769
Not Found: /favicon.ico
[03/Sep/2017 00:08:21] "GET /favicon.ico HTTP/1.1" 404 2078
testing validity
Internal Server Error: /collector/183618/submit/
Traceback (most recent call last):
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/utils/datastructures.py", line 83, in __getitem__
    list_ = super(MultiValueDict, self).__getitem__(key)
KeyError: 'form-0-id'

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "/home/user/Documents/site/crowdsource/collector/views.py", line 87, in submit
    if modelformset.is_valid():
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/forms/formsets.py", line 321, in is_valid
    self.errors
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/forms/formsets.py", line 295, in errors
    self.full_clean()
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/forms/formsets.py", line 344, in full_clean
    form = self.forms[i]
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/utils/functional.py", line 35, in __get__
    res = instance.__dict__[self.name] = self.func(instance)
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/forms/formsets.py", line 144, in forms
    for i in range(self.total_form_count())]
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/forms/formsets.py", line 144, in <listcomp>
    for i in range(self.total_form_count())]
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/forms/models.py", line 603, in _construct_form
    pk = self.data[pk_key]
  File "/home/user/Documents/site/venv/lib/python3.6/site-packages/django/utils/datastructures.py", line 85, in __getitem__
    raise MultiValueDictKeyError(repr(key))
django.utils.datastructures.MultiValueDictKeyError: "'form-0-id'"
[03/Sep/2017 00:09:02] "POST /collector/183618/submit/ HTTP/1.1" 500 112006

testing validity viene da ciò che ho aggiunto in risposta a una risposta proposta di seguito.

print('testing validity')
if modelformset.is_valid():
    print('saving')
    modelformset.save()

Visualizza sorgente in Chrome (nomi di campi resi anonimi, nessuno dei quali è id ):

<html>

<link rel="stylesheet" type="text/css" href="/static/style.css" />
<script type="text/javascript" src="/static/admin/js/vendor/jquery/jquery.js"></script>
<body>

<div class="top">

  <div class="div-img sub">
    <img id="clip"  src="/static/lists_of_men_cropped/41550_1821100522_1170-01047.jpg"/>
  </div>


  <div class="div-table sub">
    <form action="/collector/183618/submit/" method="POST" enctype="multipart/form-data">
      <input type='hidden' name='csrfmiddlewaretoken' value='GGVRrXaNH46axDImq2DEjEtV4mAaIiVLMpK6fpgyLXpLeVrIVOGICZ0SIMGtxeDV' />
      <input type="hidden" name="form-TOTAL_FORMS" value="10" id="id_form-TOTAL_FORMS" /><input type="hidden" name="form-INITIAL_FORMS" value="10" id="id_form-INITIAL_FORMS" /><input type="hidden" name="form-MIN_NUM_FORMS" value="0" id="id_form-MIN_NUM_FORMS" /><input type="hidden" name="form-MAX_NUM_FORMS" value="1000" id="id_form-MAX_NUM_FORMS" />

      <table id="id_data_table">

          <input type="hidden" name="id" id="id_id" />

          <thead><tr>

              <th>field 1</th>

              <th>field 2</th>

              <th>field 3</th>

              <th>field 4</th>

              <th>field 5</th>

              <th>field 6</th>

              <th>field 7</th>

              <th>field 8</th>

              <th>field 9</th>

          </tr></thead>

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

          <input type="hidden" name="id" id="id_id" />

        <tr>

            <td>
              <input type="text" name="field_1" id="id_field_1" />
            </td>

            <td>
              <input type="text" name="field_2" id="id_field_2" />
            </td>

            <td>
              <select name="field_3" id="id_field_3">
  <option value="" selected>     </option>

  <option value="0">option a</option>

  <option value="1">option b</option>

  <option value="2">option c</option>

  <option value="3">option d</option>

  <option value="4">option e</option>

  <option value="5">option f</option>

  <option value="6">option g</option>

  <option value="7">option h</option>

  <option value="8">option i</option>

  <option value="9">option j</option>

</select>
            </td>

            <td>
              <input type="text" name="field_4" id="id_field_4" />
            </td>

            <td>
              <input type="text" name="field_5" id="id_field_5" />
            </td>

            <td>
              <input type="text" name="field_6" id="id_field_6" />
            </td>

            <td>
              <input type="text" name="field_7" id="id_field_7" />
            </td>

            <td>
              <input type="checkbox" name="field_8" id="id_field_8" />
            </td>

            <td>
              <input type="checkbox" name="field_9" id="id_field_9" />
            </td>

        </tr>

    </table>
    <p/>
    <div class="div-submit">
          <input type="submit"/>
    </div>
  </form>

</div>

</div>

</body>

<script>
  function copyTextValue(bf) {
    var text = document.getElementsByClassName("call-number")[0].value ;
    elements = document.getElementsByClassName("call-number");
    for (var i = 0; i < elements.length; i++){
      elements[i].value = text
    }
  }
</script>

</html>




django-forms