python - tutorial - Django formset plantea KeyError `form-0-id`
forms meta django (1)
Intento guardar un formset pero sigo recibiendo
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
plantea el mismo error.
Aquí hay una pregunta que parece muy cercana, pero agregar {{form.id}}
justo antes del {%for field in form.visible_fields %}
no parece ayudar.
Hay un campo de id
autogenerado en la tabla de la base de datos, pero no se especifica explícitamente en el modelo (no estoy seguro si eso es relevante). id
no aparece en ninguno de los códigos o campos, ni en el código del modelo. id
es solo una columna de base de datos generada automáticamente por migrate
.
Aquí está la vista que publico en:
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 = {
...
}
Aquí está la plantilla que hace la publicación:
<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>
entonces cada fila es una forma y cada columna un campo:
rastrear:
[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
proviene de esto que agregué en respuesta a una respuesta propuesta a continuación.
print(''testing validity'')
if modelformset.is_valid():
print(''saving'')
modelformset.save()
Ver fuente en Chrome (nombres de campo anónimos, ninguno de ellos es 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>
Creo que debe llamar a is_valid
antes de guardar el formset, incluso si está 100% seguro de que los formularios son válidos:
if modelformset.is_valid():
modelformset.save()