Hamid
Hamid

Reputation: 11

keyerror in formset form field

I am making a delivery note transaction form, I have created a formset for which I want Django to ignore item transactions where the item is not selected and is empty.

forms.py

class Delivery_note_transiction_form(forms.Form):

    item = forms.CharField(widget=Select2Widget(attrs={"class" : "item"}),label=False,required=False)
    description = forms.CharField(widget=forms.TextInput(attrs={ 'placeholder' : 'optionall','class' : 'description'}),label=False,required=False)
    quantity = forms.IntegerField(widget=forms.NumberInput(attrs={'class' : 'quantity'}),label=False,min_value=1)
    id = forms.CharField(widget=forms.HiddenInput,required=False)

Delivery_note_transiction_form_formset = forms.formset_factory(Delivery_note_transiction_form,extra=1)

views.py

def feedback(request):
     if request.method == "POST" and request.is_ajax():
         form = Deliver_Note_Main_Modelform(request.POST)
         formset = Delivery_note_transiction_form_formset(request.POST,request.FILES)
    if form.is_valid() and formset.is_valid():

        ins = form.save(commit=False)
        ins.author = request.user

        result = Customer_data.objects.get(pk=form.cleaned_data['customer'])

        ins.customer_list = result
        ins.save()


        max_invoice = Invoice_max.objects.get(invoice_name='delivery')
        max_invoice.invoice_no = max_invoice.invoice_no + 1
        max_invoice.save()

        print(formset)
        for instant in formset:
            if instant.cleaned_data['item']:

                item = Product.objects.get(pk=instant.cleaned_data['item'])
                description = instant.cleaned_data['description']
                quantity = instant.cleaned_data['quantity']
                Delivery_Note_Transiction.objects.create(
                item=item,
                description=description,
                quantity=quantity,
                delivery_invoice_no=ins
            )

        return JsonResponse({'success':True, 'next' : reverse_lazy('delivery note:delivery note home page')})

    else:
        return render(request,"delivery_note/ajax/delivery note error message.html",{"error" : form, "transiction_error": formset})
return HttpResponse("Hello from feedback!")

template.html

{% for delivery in delivery_transiction %}
    <tr class=" delivery_form ">
        <td class="col-sm-4">{{ delivery.item|as_crispy_field }}</td>
        <td class="col-sm-4">{{ delivery.description|as_crispy_field }}</td>
        <td class="col-sm-4">{{ delivery.quantity|as_crispy_field }}</td>
    </tr>
{% endfor %}

The post data is sent by Ajax and the selected option is created on the template. When it is loaded, a new row is added by Ajax. The problem is I want to it ignore transaction entry if the item is not selected or is empty, but when I run it, it gives this error:

"KeyError: 'item'"

It should ignore empty or not selected items. This only happens when the item is not selected in the transaction. I want to fix this error so that it will simply ignore rows in which the item is not selected.

Upvotes: 1

Views: 122

Answers (1)

Carl Brubaker
Carl Brubaker

Reputation: 1655

You have to use a try except when searching a dictionary for a key.

for instant in formset:
    try:
        item = Product.objects.get(pk=instant.cleaned_data['item'])
    Except KeyError:
        # What to do if no 'item'.

You will have to figure out where to put the rest of your code, but this will get you past the KeyError.

Upvotes: 1

Related Questions