Noiseapps
Noiseapps

Reputation: 77

MultiValueDictKeyError while submitting django formset

i'm working on a Django app where I am trying to submit a form and a formset in one go.

Getting the formset to render works flawlessly, but submitting it with a POST generates an error... Once i comment out generating the formset from POST data, all works fine, and the form submits without errors

The thing is, the error I get is not very descriptive:

MultiValueDictKeyError at /questions/question/add
'0'

these are my view methods:

def get(self, request, question_id=-1):
    initial_data = {
        'categories': 1,
        'subcategories': 2,
        'questionEditor': "Test initial",
        'isOpenQuestion': True,
        'isMultiChoice': False,
    }

    category = request.session['category'] if 'category' in request.session else 0
    initial_data['categories'] = category

    formset_initial_data = list()
    if question_id > 0:
        question = Question.objects.get(id=question_id)
        initial_data = {
            'categories': question.subcategories.category.id,
            'subcategories': question.subcategories.id,
            'questionEditor': question.description,
            'isOpenQuestion': question.isOpenQuestion,
            'isMultiChoice': question.isMultiChoice,
        }

        for index, answer in enumerate(question.answer_set.all()):
            print answer.description
            formset_initial_data.append({
                'formulaAnswerEditor': answer.description,
                'answerInputBox': answer.isCorrect,
            })

    question_edit_formset = formset_factory(forms.QuestionEditAnswerForm, extra=(3 if len(formset_initial_data) == 0 else 0))
    formset = question_edit_formset(initial=formset_initial_data)

    form = forms.QuestionEditForm(data=initial_data)
    data = {
        'form': form,
        'formset': formset,
    }
    return render(request, "questionEdit.html", dictionary=data)


def post(self, request, question_id=-1):
    print request.POST
    form = forms.QuestionEditForm(data=request.POST)
    question_answers_formset = formset_factory(forms.QuestionEditAnswerForm, extra=0)
    formset = question_answers_formset(initial=request.POST)

    print form, formset

the form class

class QuestionEditAnswerForm(forms.Form):
    id = forms.IntegerField(widget=forms.HiddenInput())
    answerInputBox = forms.BooleanField(required=False, widget=forms.CheckboxInput(attrs={
        'class': 'answer-input-type',
        'type': 'radio',
    }))

    formulaAnswerEditor = forms.CharField(widget=forms.Textarea(attrs={
        'class': "answer-text-area-style answer-cke-remove-bottom-toolbar cke-placeholder"}))

template:

{{ formset.management_form }}

{% for single_answer in formset %}

    {{ single_answer.id }}
    <div class="margin-answer">
        <div class="input-group">
            <span class="input-group-addon">
                {{ single_answer.answerInputBox }}
            </span>
            {{ single_answer.formulaAnswerEditor }}
        </div>
    </div>
{% endfor %}

new forms to the formset are added using JS, but even if I don't add any new form, the error persists...

I have tried following answers to similar questions, but so far with no luck

If anyone knows how to figure this out, I'd be grateful :)

EDIT: full traceback (i'm relatively new to Django and Python, so that doesn't say too much to me :))

Request Method: POST
Request URL: http://localhost:8000/questions/question/add

Django Version: 1.9.6
Python Version: 2.7.11
Installed Applications:
['suit',
 'django.contrib.admin',
 'django.contrib.auth',
 'django.contrib.contenttypes',
 'django.contrib.sessions',
 'django.contrib.messages',
 'django.contrib.staticfiles',
 'MainPage',
 'News',
 'Registration',
 'StaticSites',
 'UserDetails',
 'Questions',
 'Competitions']
Installed Middleware:
['django.middleware.security.SecurityMiddleware',
 'django.contrib.sessions.middleware.SessionMiddleware',
 'django.middleware.common.CommonMiddleware',
 'django.middleware.csrf.CsrfViewMiddleware',
 'django.contrib.auth.middleware.AuthenticationMiddleware',
 'django.contrib.auth.middleware.SessionAuthenticationMiddleware',
 'django.contrib.messages.middleware.MessageMiddleware',
 'django.middleware.clickjacking.XFrameOptionsMiddleware']



Traceback:

File "/path/to/env/env/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  149.                     response = self.process_exception_by_middleware(e, request)

File "/path/to/env/env/lib/python2.7/site-packages/django/core/handlers/base.py" in get_response
  147.                     response = wrapped_callback(request, *callback_args, **callback_kwargs)

File "/path/to/env/env/lib/python2.7/site-packages/django/views/generic/base.py" in view
  68.             return self.dispatch(request, *args, **kwargs)

File "/path/to/env/env/lib/python2.7/site-packages/django/views/generic/base.py" in dispatch
  88.         return handler(request, *args, **kwargs)

File "/path/to/env/ekonkurs/Questions/views.py" in post
  221.         print form, formset

File "/path/to/env/env/lib/python2.7/site-packages/django/utils/six.py" in <lambda>
  842.         klass.__str__ = lambda self: self.__unicode__().encode('utf-8')

File "/path/to/env/env/lib/python2.7/site-packages/django/utils/html.py" in <lambda>
  381.         klass.__unicode__ = lambda self: mark_safe(klass_unicode(self))

File "/path/to/env/env/lib/python2.7/site-packages/django/forms/formsets.py" in __str__
  70.         return self.as_table()

File "/path/to/env/env/lib/python2.7/site-packages/django/forms/formsets.py" in as_table
  413.         forms = ' '.join(form.as_table() for form in self)

File "/path/to/env/env/lib/python2.7/site-packages/django/forms/formsets.py" in __iter__
  74.         return iter(self.forms)

File "/path/to/env/env/lib/python2.7/site-packages/django/utils/functional.py" in __get__
  33.         res = instance.__dict__[self.name] = self.func(instance)

File "/path/to/env/env/lib/python2.7/site-packages/django/forms/formsets.py" in forms
  144.                  for i in range(self.total_form_count())]

File "/path/to/env/env/lib/python2.7/site-packages/django/forms/formsets.py" in _construct_form
  170.                 defaults['initial'] = self.initial[i]

File "/path/to/env/env/lib/python2.7/site-packages/django/utils/datastructures.py" in __getitem__
  85.             raise MultiValueDictKeyError(repr(key))

Exception Type: MultiValueDictKeyError at /questions/question/add
Exception Value: '0'

Upvotes: 1

Views: 1137

Answers (1)

Daniel Roseman
Daniel Roseman

Reputation: 599778

The problem is in your post method: you're passing the data to the formset as the initial parameter, rather than data as you do with the form.

(Note that you seem to be making the opposite mistake in the get method; you're passing initial data to the form as data, rather than initial.)

Upvotes: 1

Related Questions