Reputation: 4045
I have a formset (InvoiceItemForm
) where the initial form is created by Django, but for adding aditional forms to the formset I use Jquery.
Inside this forms there is a select field (product
). The first form of the select is generated by ModelChoiceField
, but the rest are generated and populated dynamically using ajax.
When I get the request, the first one (generated by django) does not have problems, but the rest show this form.error in the product field: Select a valid choice. That choice is not one of the available choices.
What I am doing wrong? I checked the forms and I don't see differences between the generated by ModelChoiceField
and the ones with Jquery
Model
class Invoice(models.Model):
number = models.CharField(max_length=200)
def __str__(self):
return self.number
class Product(models.Model):
description = models.CharField(max_length=200)
measurement_unit = models.CharField(max_length=200)
def __str__(self):
return self.description
class InvoiceItem(models.Model):
invoice = models.ForeignKey(Invoice, related_name='items')
product = models.ForeignKey(Product)
unit_price = models.DecimalField(max_digits=8, decimal_places=2, default=0)
quantity = models.DecimalField(max_digits=8, decimal_places=2, default=0)
Forms.py
class InvoiceItemForm(forms.Form):
product = forms.ModelChoiceField(queryset=Product.objects.all().order_by('description'))
unit_price = forms.DecimalField(max_digits=8, decimal_places=2,
widget=forms.TextInput(attrs={'placeholder': 'Precio', 'class': 'rate'}))
quantity = forms.DecimalField(max_digits=8, decimal_places=2,
widget=forms.TextInput(attrs={'placeholder': 'Cantidad', 'class':'quantity'}))
class InvoiceForm(forms.Form):
number = forms.CharField()
Views.py
def invoice(request):
InvoiceFormSet = formset_factory(InvoiceItemForm)
if request.method == 'POST':
invoice_form = InvoiceForm(request.POST)
formset = InvoiceFormSet(request.POST)
if invoice_form.is_valid():
# print("invoice number: ", invoice_form.cleaned_data['number'])
number = invoice_form.cleaned_data['number']
invoice = Invoice(number=number)
for form in formset:
print(form.errors)
Ajax for populating Select Field
$.ajax({
url: '/ajax/get_products/',
type: 'GET',
data: {},
dataType: 'json',
success: function(data){
let selectItem = $(`#id_form-${total_forms-1}-product`)
selectItem.append(new Option("---------", "", false, false))
for (let i=0; i < data['products'].length; i++){
let p = data['products'][i][0] //product name
selectItem.append(new Option(p, p, false, false))
}
$('select').material_select()
}
})
Upvotes: 1
Views: 1764
Reputation: 885
This is due to the way Django validates forms.
To put it simply, it does not expect to be answered a choice that it did not generate.
In the docs : https://docs.djangoproject.com/en/1.11/ref/forms/fields/#choicefield
Validates that the given value exists in the list of choices.
A simple "Django ajax choice form" search on this site will return you some possible workarounds.
Upvotes: 2