Home > OS >  Django Many-To-Many through form with specific queryset
Django Many-To-Many through form with specific queryset

Time:07-14

I have the following models Program and Exam with foregin keys to University.

class Program(models.Model):
    university = models.ForeignKey(University, on_delete=models.CASCADE)
    ...
    exams = models.ManyToManyField(Exam, through='ProgramExam')

class Exam(models.Model):
    university = models.ForeignKey(University, on_delete=models.CASCADE)
    ...

And they have a many-to-many relation through the model ProgramExam which adds extra fields.

class ProgramExam(models.Model):
    program = models.ForeignKey(Program, on_delete=models.CASCADE)
    exam = models.ForeignKey(Exam, on_delete=models.DO_NOTHING)
    coef = models.FloatField(
        validators=[MinValueValidator(0.0), MaxValueValidator(3.0)]
    )

    class Meta:
        unique_together = [['program', 'exam']]

How do I set the queryset in forms.ModelChoiceField so to only display instances of Exam that have the same ForeignKey as the instance of Program

class ProgramExamForm(forms.ModelForm):
    exam = forms.ModelChoiceField(queryset=Exam.objects.none())

I tried passing a queryset in my view but it interferes with request.POST

def create_program(request):
    user = request.user
    exams = user.university.exam_set.all()
    program_exam_form = ProgramExamForm()
    program_form.fields['exam'].queryset = exams


    if user:
        if hasattr(user, 'university'):
            if request.method == 'POST':
                program_exam_form = ProgramExamForm(request.POST)

                if program_exam_form.is_valid():
                    program_exam = program_exam_form.save()
                    ...

            context = {'program_exam_form': program_exam_form}
            return render(request, 'create_program.html', context)

CodePudding user response:

Simply set the queryset after you reinitialize the ProgramExamForm:

def create_program(request):
    ...

    if user:
        if hasattr(user, 'university'):
            if request.method == 'POST':
                program_exam_form = ProgramExamForm(request.POST)
                program_form.fields['exam'].queryset = exams  # here
    ...
  • Related