So I am trying to make a student result management project. Where I can add students subject grade and exam result. In the project i need to make a form where i can add marks of a subject to all the students of a grade(Class) at once. I want the look like the photo. Example Example .
I tried to create individual form for every sector and try to combine them. But it didn't work. Now I need to know how can I make a form using many models in Django.
As far as I understand you want to create a form in Django that handles multiple models at once, well you can use ModelForm combined with inline formsets, by using inline formsets in Django, you can manage forms for multiple related models (like Student
, Subject
, and ExamResult
) in one form. This is a clean and efficient way to manage forms for related data, and it avoids the complexity of manually creating individual forms for each record. If you want to learn more about inline formsets
click here.
Let's do this step-by-step:
Create four models Grade
, Subject
, Student
, ExamResult
.
from django.db import models
class Grade(models.Model):
name = models.CharField(max_length=50)
class Subject(models.Model):
name = models.CharField(max_length=100)
class Student(models.Model):
first_name = models.CharField(max_length=100)
last_name = models.CharField(max_length=100)
grade = models.ForeignKey(Grade, on_delete=models.CASCADE)
class ExamResult(models.Model):
student = models.ForeignKey(Student, on_delete=models.CASCADE)
subject = models.ForeignKey(Subject, on_delete=models.CASCADE)
marks = models.DecimalField(max_digits=5, decimal_places=2)
For each model, create a ModelForm which helps in generating the form fields dynamically.
from django import forms
from .models import ExamResult
class ExamResultForm(forms.ModelForm):
class Meta:
model = ExamResult
fields = ['subject', 'marks'] # Specify the fields you want in the form
Create an inline formset for the ExamResult
model.
from django.forms import modelformset_factory
from django.forms.models import inlineformset_factory
from .models import Student, ExamResult, Subject
def exam_result_formset(request, grade_id):
students = Student.objects.filter(grade_id=grade_id)
subjects = Subject.objects.all()
formsets = []
for student in students:
for subject in subjects:
formset = inlineformset_factory(Student, ExamResult, fields=('subject', 'marks'), extra=1)
formset_instance = formset(queryset=ExamResult.objects.filter(student=student, subject=subject))
formsets.append((student, subject, formset_instance))
return render(request, 'exam_results_form.html', {'formsets': formsets})
Create a template that will loop through all formsets and render them in the HTML form.
<form method="post">
{% csrf_token %}
{% for student, subject, formset in formsets %}
<h3>{{ student.first_name }} - {{ subject.name }}</h3>
<div>
{% for form in formset %}
<div>{{ form.as_p }}</div>
{% endfor %}
</div>
{% endfor %}
<button type="submit">Save Results</button>
</form>
When the form is submitted, you can process the data and save the results in views.py
file.
def save_exam_results(request, grade_id):
if request.method == 'POST':
formsets = []
students = Student.objects.filter(grade_id=grade_id)
subjects = Subject.objects.all()
for student in students:
for subject in subjects:
formset = inlineformset_factory(Student, ExamResult, fields=('subject', 'marks'), extra=1)
formset_instance = formset(request.POST)
if formset_instance.is_valid():
formset_instance.save()
else:
formsets.append((student, subject, formset_instance))
return redirect('exam_results_list') # Redirect to a page with results or confirmation
Thank you and have a good rest of your day buddy:)