In my app, i have a dropdown (department) that's depending on the previously selected value from a dropdown(faculty field). I am using ajax to get the new value which works fine. However, when i try saving the form, i get Select a valid choice. That choice is not one of the available choices.
Here is my model
from django.db import models
from system.models import FacultyData, DepartmentData, SessionData, SemesterData, SettingsData
# Create your models here.
class SchoolFees(models.Model):
fid = models.ForeignKey(FacultyData, on_delete= models.SET_NULL, null=True)
did = models.ForeignKey(DepartmentData, on_delete= models.SET_NULL, null=True)
sid = models.ForeignKey(SessionData, on_delete= models.SET_NULL, null=True)
amount = models.CharField(max_length=30)
def __str__(self):
return self.amount
and my form.py
from django import forms
from . import models
from system.models import FacultyData, DepartmentData, SessionData
from .models import SchoolFees
class FeesCreationForm(forms.ModelForm):
fid = forms.ModelChoiceField(queryset=FacultyData.objects.all(), empty_label="--Select Faculty--",
widget=forms.Select(attrs={'class': 'form-control'}))
did = forms.ModelChoiceField(queryset=DepartmentData.objects.all(), empty_label="--Select Faculty First--",
widget=forms.Select(attrs={'class': 'form-control'}))
sid = forms.ModelChoiceField(queryset=SessionData.objects.all(), empty_label="--Select Session--",
widget=forms.Select(attrs={'class': 'form-control'}))
class Meta:
model = models.SchoolFees
fields = ['sid', 'fid', 'did', 'amount']
widgets = {
'amount': forms.TextInput(attrs={'class': 'form-control', 'placeholder': 'Enter Amount'})
}
def __init__(self, *args, **kwargs):
super(FeesCreationForm, self).__init__(*args, **kwargs)
self.fields['did'].queryset = DepartmentData.objects.none()
# Get did queryset for the selected fid
if 'fid' in self.data:
try:
fd = int(self.data.get('fid'))
self.fields['did'].queryset = DepartmentData.objects.filter(fid=fd).order_by('dept_name')
except (ValueError, TypeError):
pass # invalid input from the client; ignore and use empty queryset
in my view.py, i have a method for getting department based on the faculty chosen. and also for saving the new fee
def create_fee(request):
app = settings.CONFIG
#table = FacultyTable(FacultyData.objects.all())
# RequestConfig(request, paginate={'per_page': 10}).configure(table)
context = {"form": FeesCreationForm, 'app': app}
return render(request, 'bursary.html', context)
def get_department(request):
fid = request.GET.get('fid', None)
datas = {
'is_taken': DepartmentData.objects.filter(fid=fid)
}
department = list(DepartmentData.objects.filter(fid=fid).values())
data = dict()
data['department'] = department
return JsonResponse(data)
def save_fee(request):
app = settings.CONFIG
# table = FacultyTable(FacultyData.objects.all())
# RequestConfig(request, paginate={'per_page': 10}).configure(table)
form = FeesCreationForm(request.POST)
context = {"form": FeesCreationForm, 'app': app}
if form.is_valid():
form.save()
messages.add_message(request, messages.SUCCESS, "Fees added successfully")
else:
messages.add_message(request, messages.ERROR, form.errors)
return redirect('bursary:create_fee')
i don't know where i am getting this wrong or how to fix it
This is because you initialize your queryset empty (which is fine), but never update it within the form object itself. So the server side validation is failing.
Try updating your queryset in the __init__
method of your FeesCreationForm:
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
# Init empty did queryset
self.fields['did'].queryset = DepartmentData.objects.none()
# Get did queryset for the selected fid
if 'fid' in self.data:
try:
fid = int(self.data.get('fid'))
self.fields['did'].queryset = DepartmentData.objects.filter(
fid=fid).order_by()
except (ValueError, TypeError):
# invalid input from the client; ignore and use empty queryset
pass