Friday, January 27, 2017

MultiValueDictKeyError on 'for' loop

I have Django site, which I am using to manage various projects and the information about each project.

I have models for Projects and Budgets in the database. Each Project can have many Budgets, but a Budget can only be associated with one Project.

I am trying to add the functionality to upload an image file to a Budget using a form on one of the webpages, but am getting an error whenever I try to upload the file...

The form in the template where I am trying to upload the file is:

<form method="POST" enctype="multipart/form-data" data-vat-status="{{project.vat_status}}" data-view-url="{% url 'projects:concept_save_ajax_2' project.id %}" class="autosave_form formset full-width" action="{% url 'projects:upload_budget_pdfs' project.id %}">
{% csrf_token %}
<div id="presentations" class="app-wrap center-apps middle">
{% with get|apps:'Budgets' as costing_app %}
{% for presentation in presentations %}
<div id="presentation-{{presentation.id}}" class="app sm {% if presentation.current_marker %}{{costing_app.color}}{% else %}{{app.color}}{% endif %}">
<a href="" class="filler"></a>
<a class="show-presentation bottom-right" name="presentation-{{presentation.id}}"><img class="icon" src="{% static 'img/edit-white.png' %}"></a>

<ul class="flush">
<li class=""><h2 class="p-t-lg">Presentation {{forloop.counter}}</h2></li>
<li>{{presentation.presentation_date|date:"d M y"|xor}}</li>
<li>{{presentation.details|xor|truncatechars:50}}</li>
{% if presentation.current_marker %}<li>({% if project.deposit_received%}Deposit{% else %}Current{% endif %} budget)</li>{% endif %}
</ul>
</div>
{% if forloop.last %}
{% endif %}

{% endfor %}
{# Add a new presentation #}
<div id="presentation-new" class="app sm {{costing_app.color}} outline">
<a id="new_presentation" data-view-url="{% url 'projects:save_new_presentation' project.id %}" class="filler show-presentation" name="presentation-new"></a>
<a name="presentation-new"></a>
<span class="big-head">+</span>
<h2 class="no-m">Add presentation</h2></li>
</div>
{% endwith %}
</div>

<div class="middle">
{{presentation_formset.management_form}}
{{drawing_formset.management_form}}

<div class="col-9 centered-block p-t-lg">
<table class="left fixed text-sm slim">
{# New presentation without budget #}
<tbody>
</tbody>


{# Edit presentation details #}
{% for presentation_form in presentation_formset %}
<tbody id="pres{{forloop.counter}}" class="presentation-form" name="presentation-{{presentation_form.instance.id|xor:'new'}}" style="display: none;">
{% if not forloop.last and presentation_form.instance.budget_items.count %}
<tr class="split-rows">
<td colspan="3">Exc VAT {% if not presentation_form.instance.current_marker %}{{presentation_form.instance.grand_total_exc_vat|money:'£'}}{% else %}{{project.budget_overview.updated_exc_vat|money:'£'}}{% endif %}</td>
<td colspan="3">Inc VAT {% if not presentation_form.instance.current_marker %}{{presentation_form.instance.grand_total_inc_vat|money:'£'}}{% else %}{{project.budget_overview.updated_inc_vat|money:'£'}}{% endif %}</td>
</tr>
{% endif %}
<tr>
{% for hidden in presentation_form.hidden_fields %}
<td class="hidden">{{ hidden }}</td>
{% endfor %}
</tr>
{% for field in presentation_form.visible_fields %}
<tr class="split-rows">
{% if not field.name == 'pdf_package_dep' %}
<td colspan="6"><label>{{field.label}}</label></td>
{% endif %}
</tr>
<tr class="split-rows">
<td colspan="6">
{% if not field.name == 'pdf_package_dep' %}
{% if field.name == 'presentation_date' %}
{% with presentation_form.instance.meeting as meeting %}
{% include "projects/includes/meeting_bit.html" with employee=request.user.employee meeting=meeting UID=presentation_form.instance.id %}
{% endwith %}
{# <a class="ical_trigger button" data-view-url="{% url 'events:add_to_cal' %}" {% if not field.value %}style="display:none"{% endif %}>Add to calendar</a> #}
{% else %}
{{field}}
{% endif %}
{% endif %}
</td>
</tr>
{% endfor %}
{% if presentation_form.instance.id %}
{# PDF uploads #}
{% with drawing_form=drawing_formset|getval:forloop.counter0  %}
{# budget_pdf_form=budget_pdf_formset|getval:forloop.counter0 #}
<tr>
{% if not forloop.last %}
<td colspan="3"><label>Budget PDF package</label></td>
{% endif %}

<td colspan="3"><label>Drawings</label></td>
</tr>
  
<tr>
{% if not forloop.last %}
<td colspan="3" class="center">
{% if presentation_form.instance.pdf_package_dep %}
<a class="button file-download pdf" href="{% url 'costing:pdf_open' presentation_form.instance.id %}?pdf=package_dep" target="_blank"></a><a class="pdf-clear" data-view-url="{% url 'costing:pdf_clear' presentation_form.instance.id %}?pdf=package_dep"><img class="icon m-l-sm m-b-md" src="{% static "img/bin.png" %}"></a>
{% else %}
{{presentation_form.pdf_package_dep}}
{% endif %}
</td>
{% endif %}
   {% for d_field in drawing_form.visible_fields %}
{% if drawing_form.instance.pdf %}
<td colspan="3" class="center">
<a class="button file-download pdf" href="{% url 'costing:pdf_open' presentation_form.instance.id %}?pdf=drawings" target="_blank"></a><a class="pdf-clear" data-view-url="{% url 'costing:pdf_clear' presentation_form.instance.id %}?pdf=drawings"><img class="icon m-l-sm m-b-md" src="{% static "img/bin.png" %}"></a>
</td>
{% else %}
<td colspan="3">{{d_field}}</td>
{% for d_hidden in drawing_form.hidden_fields %}
<td class="hidden">{{d_hidden}}</td>
{% endfor %}
{% endif %}
   {% endfor %}
   <tr>
    <td colspan="1" class="p-t-md"></td>
    <td colspan="4" class="p-t-md"><input type="submit" value="upload"></td>
    <td colspan="1" class="p-t-md"></td>
    </tr>
</tr>
{% endwith %}
{% endif %}


<tr>
<td colspan="3">

<a class="button email_trigger m-t-md" style="width:auto;" data-view-url="{% url 'comms:open_email_template' project.id %}?template=6&budget={{presentation_form.instance.id}}">Email client meeting report</a>
</td>
</tr>


<tr>
<td class="p-t-md">
<a {% if forloop.last %}id="refresh_presentations"{% endif %}class="update_presentation button fill">Done</a>
</td>
<td colspan="2">
{% if presentation_form.instance.id and not presentation_form.instance.budget_items.count %}
<a class="button fill" href="{% url 'costing:delete_presentation' presentation_form.instance.id %}">Delete</a>
{% endif %}
</td>
</tr>
</tbody>

{% endfor %}
</table>
</div>
</div>
</form>

and the view that is called when clicking the 'Submit' button on the form is:

def upload_budget_pdfs(request, project_id):
project = Project.objects.get(id=project_id)
print("Value of project in 'upload_budget_pdfs()': ", project)

if request.method == 'POST':
 
presentations = project.budget_versions.select_related('meeting').prefetch_related('budget_items', 'cci_items', 'presenters').filter(version_number__isnull=False).annotate(vn=F('version_number') * -1).order_by('presentation_date', 'created', '-vn')
print("Value of presentations in 'upload_budget_pdfs()': ", presentations)
drawing_formset = DrawingUploadFormset(request.POST, request.FILES, prefix="drawings", queryset=Drawing.objects.filter(budget__in=presentations).order_by('budget__presentation_date', 'budget__created'))

print("Value of drawing_formset in 'upload_budget_pdfs()': ", drawing_formset)

if drawing_formset:
print 'Saving drawing_formset'
print "Before", [b.id for b in project.budget_versions.all()]
for drawing_form in drawing_formset: # This line is what's causing the MultiValueDictKeyError
if drawing_form.instance.budget:
print 'Instance', drawing_form.instance.budget
drawing = drawing_form.save(commit=False)
drawing.budget = drawing_form.instance.budget
drawing.save()
print drawing, [b.id for b in project.budget_versions.all()]
else: 
print("Drawing formset not valid. ", drawing_formset.errors)


budget_formset = BudgetPresentationFormset(request.POST, request.FILES, instance=project, prefix="presentations")

if budget_formset.is_valid() and budget_formset.has_changed():
updated_budget_presentations = budget_formset.save()
elif budget_formset.has_changed(): print 'Budget formset not valid.',budget_formset.errors

return HttpResponseRedirect(reverse('projects:concept', args=[project_id]))

Currently, when I view this page in the browser, and the form is displayed, I can upload an image file to the form by clicking on the 'Upload' button, selecting the file, and pressing 'Ok'. I can see that the file has been 'attached' to the form correctly, as its name is displayed next to the 'Upload' button on the form.

However, when I then click the 'Submit' button, to submit the form, my browser displays an error page that says:

MultiValueDictKeyError at /projects/6215/upload-budget-pdf/

"u'drawings-4-id'"
Request Method:POST
Request URL:http://localhost:8000/projects/6215/upload-budget-pdf/
Django Version:1.9.1
Exception Type:MultiValueDictKeyError
Exception Value:
"u'drawings-4-id'"
Exception Location:/Users/.../.virtualenvs/moon/lib/python2.7/site-packages/django/utils/datastructures.py in __getitem__, line 85
Python Executable:/Users/.../.virtualenvs/moon/bin/python
Python Version:2.7.6
Python Path:
['/Users/.../Documents/Dev/moonhub/moon',   '/Users/beckysmith/Documents/Dev/moonhub/moon/moon',   '/usr/local/bin',   '/Users/.../Documents/Dev/moonhub/moon',   '/Users/.../.virtualenvs/moon/lib/python27.zip',   '/Users/.../.virtualenvs/moon/lib/python2.7',   '/Users/.../.virtualenvs/moon/lib/python2.7/plat-darwin',   '/Users/.../.virtualenvs/moon/lib/python2.7/plat-mac',   '/Users/.../.virtualenvs/moon/lib/python2.7/plat-mac/lib-scriptpackages',   '/Users/.../.virtualenvs/moon/Extras/lib/python',   '/Users/.../.virtualenvs/moon/lib/python2.7/lib-tk',   '/Users/.../.virtualenvs/moon/lib/python2.7/lib-old',   '/Users/.../.virtualenvs/moon/lib/python2.7/lib-dynload',   '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7',   '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-darwin',   '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/lib-tk',   '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac',   '/System/Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/plat-mac/lib-scriptpackages',   '/Users/elgan/.virtualenvs/moon/lib/python2.7/site-packages']
Server time:Fri, 27 Jan 2017 08:48:54 +0000

and the console displays the following output:

("Value of project in 'upload_budget_pdfs()': ", <Project: Test 1>)

("Value of presentations in 'upload_budget_pdfs()': ", [<Budget: Test 1: Version -1>, <Budget: Test 1: Version -1>, <Budget: Test 1: Version 0>, <Budget: Test 1: Version 0>, <Budget: Test 1: Version 0>, <Budget: Test 1: Version 3>, <Budget: Test 1: Version 0>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, <Budget: Test 1: Version 1234>, '...(remaining elements truncated)...'])

("Value of drawing_formset in 'upload_budget_pdfs()': ", <django.forms.formsets.DrawingFormFormSet object at 0x107036110>)

Saving drawing_formset

Before [3690L, 3691L, 3693L, 3695L, 3696L, 3697L, 3707L, 3709L, 3726L, 3727L, 3745L, 3747L, 3748L, 3749L, 3750L, 3757L, 3763L, 3766L, 3769L, 3770L, 3771L, 3772L, 3801L, 3802L, 3866L, 3867L, 3868L, 3869L, 3870L, 3871L, 3872L, 3873L, 3874L, 3875L, 3876L, 3877L, 3878L, 3879L, 3880L, 3881L, 3882L, 3883L, 3884L, 3885L, 3886L, 3887L, 3888L, 3889L, 3890L, 3891L, 3892L, 3893L, 3894L, 3895L, 3896L, 3897L, 3898L, 3899L, 3900L]

Internal Server Error: /projects/6215/upload-budget-pdf/

Traceback (most recent call last):

  File "/Users/.../.virtualenvs/moon/lib/python2.7/site-packages/django/core/handlers/base.py", line 140, in get_response

    response = middleware_method(request, callback, callback_args, callback_kwargs)

  File "/Users/.../Documents/Dev/moonhub/moon/moon/middleware.py", line 72, in process_view

    return permission_required(required_permission)(view_func)(request,*view_args,**view_kwargs)

  File "/Users/.../.virtualenvs/moon/lib/python2.7/site-packages/django/contrib/auth/decorators.py", line 23, in _wrapped_view

    return view_func(request, *args, **kwargs)

  File "/Users/.../Documents/Dev/moonhub/moon/projects/views.py", line 1034, in upload_budget_pdfs

    for drawing_form in drawing_formset: #ERF(24/01/2017 @ 1610) This line is what's causing the MultiValueDictKeyError

  File "/Users/.../.virtualenvs/moon/lib/python2.7/site-packages/django/forms/formsets.py", line 74, in __iter__

    return iter(self.forms)

  File "/Users/.../.virtualenvs/moon/lib/python2.7/site-packages/django/utils/functional.py", line 33, in __get__

    res = instance.__dict__[self.name] = self.func(instance)

  File "/Users/.../.virtualenvs/moon/lib/python2.7/site-packages/django/forms/formsets.py", line 144, in forms

    for i in range(self.total_form_count())]

  File "/Users/.../.virtualenvs/moon/lib/python2.7/site-packages/django/forms/models.py", line 587, in _construct_form

    pk = self.data[pk_key]

  File "/Users/.../.virtualenvs/moon/lib/python2.7/site-packages/django/utils/datastructures.py", line 85, in __getitem__

    raise MultiValueDictKeyError(repr(key))

MultiValueDictKeyError: "u'drawings-4-id'"

[27/Jan/2017 10:16:48] "POST /projects/6215/upload-budget-pdf/ HTTP/1.1" 500 205382




 

So it seems that the 'Internal Server Error' or 'MultiValueDictKeyError' is caused by the line: 
for drawing_form in drawing_formset:

but I don't understand why this is causing me the error...? Can anyone explain what I'm doing wrong here? Is there something wrong with the way I have declared `drawing_formset`? How can I resolve this error?



--
You received this message because you are subscribed to the Google Groups "Django users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to django-users+unsubscribe@googlegroups.com.
To post to this group, send email to django-users@googlegroups.com.
Visit this group at https://groups.google.com/group/django-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/django-users/d32da406-a1b4-4e59-b50c-d9a352c8d77f%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

No comments:

Post a Comment