3

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

2 Answers 2

6

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
3
  • 1
    the following is showing syntax error fid = int(self.data.get('fid')) | self.fields['did'].queryset = DepartmentData.objects.filter(fid=fid).order_by() Commented Jan 14, 2019 at 12:28
  • 1
    @AkinniyiBodeBolade I updated my code. There was a small typo
    – Sergio
    Commented Jan 14, 2019 at 12:50
  • 2
    i figured but i am still getting "did Select a valid choice. That choice is not one of the available choices." Commented Jan 14, 2019 at 13:05
1

(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.

1
  • Man you saved my day. This was EXACTLY my problem too.
    – Andreas
    Commented May 9, 2022 at 18:49

Not the answer you're looking for? Browse other questions tagged or ask your own question.