I have three models: Schools, Courses, and Students.
Every Course is a subject that belongs to the Schools model.
Every Student takes a course from the Course model. In this way they relate to each other. What I’m trying to do is add a new student, that selects a course from a drop-down list. However, the Course model is too large for this to be practical. I therefore wish to filter the courses by having them select a school, and that drastically lowers the list of available courses to a reasonable number. I’m not sure how to finish this.
models:
class Courses(models.Model):
id = models.CharField(primary_key=True, max_length=12)
created_at = models.DateTimeField(auto_now_add=True)
school = models.ForeignKey(School, on_delete=models.PROTECT, related_name='school')
name = models.CharField(max_length=150, null=True, blank=True)
cost = models.CharField(max_length=75, null=True, blank=True)
class Meta:
ordering = ['id']
indexes = [
models.Index(fields=['school']),
models.Index(fields=['name', 'id'])
]
def __str__(self):
return(f"{self.school} {self.name}")
return self.name
class School(models.Model):
id = models.CharField(primary_key=True, max_length=10)
school_name = models.CharField(max_length=80)
def __str__(self):
return(f"{self.id} {self.school_name}")
return self.id
class Meta:
ordering = ['id']
indexes = [
models.Index(fields=['id', 'school_name']),
]
class Student(models.Model):
course = models.ForeignKey(Courses, on_delete=models.PROTECT)
created_at = models.DateTimeField(auto_now_add=True)
student_id = models.CharField(max_length=20, null=True, blank=True)
class Meta:
ordering = ['course']
indexes = [
models.Index(fields=['course']),
]
def __str__(self):
return(f"{self.course} {self.student_id}")
views:
def add_student1(request):
schools = Courses.objects.all()
form = SelectSchoolForm(request.POST)
context = {'form':form, 'schools':schools}
if request.method == "POST":
if form.is_valid():
data = form.cleaned_data
school = data['school']
chosen_school = Courses.objects.filter(school=school).values()
context2 = {'form':form, 'schools':schools, 'chosen_school':chosen_school}
messages.success(request, 'OK')
return render(request, 'add_student2.html', {'school':school})
return render(request, 'add_student1.html', context)
def add_student2(request, school):
chosen_school = Courses.objects.filter(chosen_school=school).values()
school1 = chosen_school
form =AddStudentForm(request.POST)
context = {'form':form, 'school':school, 'school1':school1}
template = loader.get_template('add_student2.html')
return HttpResponse(template.render(context, request))
forms:
class SelectSchoolForm(forms.ModelForm):
class Meta:
model = Courses
fields = ('school', )
labels = {'school':'School', }
widgets = {'school': forms.Select(attrs={"placeholder":"School", "class":"form-select"}),
}
class AddStudentForm(forms.ModelForm):
class Meta:
model = Student
fields = ('course', 'student_id' )
labels = {'course':'','student_id':'',}
widgets = {'course': forms.widgets.Select(attrs={"placeholder":"Course", "class":"form-control"}),
'student_id':forms.widgets.TextInput(attrs={"placeholder":"Student ID", "class":"form-control"}),
}
html:
add_student1.html
<h1>Add Student</h1>
<br/>
<form class="row g-3" action="{% url 'add_student1' %}" method="POST" enctype="multipart/form-data">
{% csrf_token %}
<div class="col-md-6">
{{ form.as_p }}
</div>
add_student2.html
<h1>Add Student2</h1>
<br/>
{% if school %}
{{ school }}
{% endif %}
When I make a selection, the add_student2.html template is rendered, and it displays the selection. How do I use this to add the student with the filtered data? Alternatively, am I making this more complicated than it needs to be? I should add that a filter on the data is necessary due to the large number of course in the Course model.