Home > Software engineering >  How to properly bind a Django form?
How to properly bind a Django form?

Time:09-01

I am working on a form that picks a Sale id and submits it to the server. When i submit it to the server a bind it using form = DeleteSalesForm(request.POST) and check it form.is_bound returns False. This is my views.py

def delete_sales(request):
    if not request.user.is_authenticated:
        return redirect('/login')
    if request.method == 'GET':
        form = DeleteSalesForm()
        print("GET")
        return render(request, 'inventorymanagment/delete_sales.html', {'form': form})
    form = DeleteSalesForm(request.POST)
    print("checking if form is valid", request.POST, form.is_bound, form)
    if form.is_valid():
        form.delete_sale()
        # redirect
        return redirect('/')
    else:
        print("sale not deleted")
        # why is the form invalid?
        print(form.errors)
        return render(request, 'inventorymanagment/delete_sales.html', {'form': form})

Here is forms.py

class DeleteSalesForm(ModelForm):
    class Meta:
        model = Sales
        fields = ['id']
        labels = {
            'id': 'Sale',
        }

    def clean(self):
        self.cleaned_data = super().clean()
        id = int(self.cleaned_data.get('id')[0])
        print('id', id)
        if id <= 0:
            raise forms.ValidationError('ID cannot be negative')
        print('id > 0', id)
        # check if id in database
        if id not in Sales.objects.all().values_list('id', flat=True):
            raise forms.ValidationError('ID not in database')
        print("id in database", id)
        return id

    def __init__(self, *args, **kwargs):
        super().__init__()
        self.fields['id'] = forms.ChoiceField(
            label="Sale", choices=[(i.id, i) for i in Sales.objects.all()], required=True)

    def delete_sale(self):
        id = self.cleaned_data.get('id')
        print('id', id)
        sale = Sales.objects.get(id=id)
        print('sale', sale)
        item = sale.item
        print('item', item)
        item.remaining  = sale.quantity
        item.sold -= sale.quantity
        item.save()
        sale.delete()
        return True

    def validate_unique(self) -> None:
        print("validate_unique")
        return super().validate_unique()

    def validate_constraints(self) -> None:
        print("validate_constraints")
        return super().validate_constraints()

Here is the traceback:

[31/Aug/2022 15:38:36] "POST /delete_sales HTTP/1.1" 200 932
checking if form is valid <QueryDict: {'csrfmiddlewaretoken': ['q3aga7bySuscQ6bb9zrh3pFUlfoIoRoGQnHvQQ8LlbiEfUl1XDSGp2fk3nCj5KJk'], 'id': ['16']}> False <tr>
    <th><label for="id_id">Sale:</label></th>
    <td>

      <select name="id" id="id_id">
  <option value="16">id: 16, iphone 6 quantity: 50 price: 30.00 day: 2022-08-31</option>

  <option value="17">id: 17, Iphone 8 quantity: 70 price: 80.00 day: 2022-08-31</option>

</select>




    </td>
  </tr>
sale not deleted

why isn't the form validating?

CodePudding user response:

Well, you are currently overwriting the __init__ method of the form incorrectly.

Try passing in the *args and **kwargs as arguments to constructor method of the parent class.

def __init__(self, *args, **kwargs):
    super().__init__(*args, **kwargs)
    self.fields['id'] = forms.ChoiceField(
    label="Sale", choices=[(i.id, i) for i in Sales.objects.all()], required=True)
  • Related