How can I set form multiple choice options with values from a database?

I’m trying to make it so that I have a form appear on the screen with the options being all the classes the teacher has created. This means I’ll be getting the class names that the teacher teaches from my database and setting these as the options in the form. I wasn’t really sure whether to use ModelForm or Form since my form relies on database data but doesn’t actually store anything in the database. I’ve tried using both types of forms and failed epically so I’d appreciate some help. Currently the form appears on the screen, but the class options aren’t.

forms.py

class SetAsAssignment(forms.Form):

        def __init__(self, currentteacherid, *args, **kwargs):
            super(SetAsAssignment, self).__init__(*args, **kwargs)
            self.fields['classes'] = forms.MultipleChoiceField(choices = [(o.class_name, str(o)) for o in Class.objects.filter(teacher_id__in=currentteacherid)])

views.py

def set_as_assignment(request):
        currentusername = request.user.username
        currentteacher = Teacher.objects.filter(username__in=currentusername).values_list('teacher_id', flat=True)
        set_as_assignment_form = SetAsAssignment(currentteacherid=currentteacher)
        return render(request, 'set_as_assignment.html', {'set_as_assignment_form': set_as_assignment_form})

models.py

class Teacher(User):
    teacher_id = models.AutoField(primary_key=True)

    def __str__(self):
        return self.username

class Class(models.Model):
    class_code = models.AutoField(primary_key=True)
    class_name = models.TextField()
    teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)

    def __str__(self):
        return self.class_name

html

 <div class="container">
        <form> 
            {% csrf_token %}
            {{ set_as_assignment_form }}
            <button type="submit" class="btn btn-custom">SET</button>
        </form>
  </div>

Thankyou in advance :))

Is that the complete form shown in the snippet at the top, or is there more to the form than that.

Also, have you verified that in your test case, currentteacher contains an iterable for any given request? (In other words, have you verified that your query works for the information available at the point where the query is running?)

This query can result in an empty result set if either the current user isn’t a teacher or has a blank username.

Since there’s only one Teacher for any given username, I would suggest that you change the filter to a get to retrieve the specific Teacher object, access the teacher_id field directly, pass it to the form, and change your filter in the Class query to an exact match.

Also note that since there’s a foreign key relationship between Teacher and Class, you don’t need to write an explicit query to retrieve those related objects.

Given an instance of Teacher named teacher, then teacher.class_set.all() is the set of all classes related to teacher. You can iterate over that set directly.

2 Likes