问题
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
回答1:
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
回答2:
(paraphrasing)
I have a dropdown that's depending on a previously selected value from another dropdown
I had a similar problem in the past. Does this answer your question? The basic idea is, you can send all the correct information to the client you want, but at the end of the day the server should be validating that the correct set of options were used. Django is getting mad because it thinks the choice sent to the server for the 2nd dropdown is invalid. After receiving the POST, you need to dynamically get the 2nd dropdown's choices BASED ON whatever was sent as dropdown #1's choice AND THEN try and validate the form.
来源:https://stackoverflow.com/questions/54181253/select-a-valid-choice-that-choice-is-not-one-of-the-available-choices