the goal of my code is to make a school management system where the admin can log in and add teachers to their respective classes that they are leading and be able to add students to their respective classes and then take the attendance of those students present on any given day. however, I am having an issue where the form to add the student to the class isn't rendering when I click on the add student button. I have been searching but can't seem to find the error in my code, I am new to Django so any help will be appreciated. the closest I got was to make the modal show up but the fields to select the student from to add to the class wasn't showing
models
class Teacher(models.Model):
first_name = models.CharField(max_length=60, blank=False, null=False)
last_name = models.CharField(max_length=80, blank=False, null=False)
address = models.CharField(max_length=120, blank=True, null=True)
contact = models.CharField(max_length=10, blank=True, null=True)
email = models.EmailField(blank=True, null=True)
birth = models.CharField(max_length=20, blank=True, null=True)
gender = models.CharField(max_length=100, choices=[('Male', 'Male'), ('Female', 'Female')], blank=True, null=True)
comment = models.TextField(max_length=10000, blank=True, null=True)
def __str__(self):
return f"{self.first_name ' ' self.last_name}"
class Student(models.Model):
student_code = models.CharField(max_length=250, blank=True, null=True)
first_name = models.CharField(max_length=20, blank=False, null=False)
last_name = models.CharField(max_length=20, blank=False, null=False)
address = models.CharField(max_length=120, blank=True, null=True)
contact = models.CharField(max_length=10, blank=True, null=True)
admission = models.CharField(max_length=20, blank=True, null=True)
birth = models.CharField(max_length=20, blank=True, null=True)
parents = models.CharField(max_length=200, blank=False)
gender = models.CharField(max_length=100, choices=[('Male', 'Male'), ('Female', 'Female')], blank=True, null=True)
comment = models.TextField(max_length=10000, null=True, blank=True)
passport = models.ImageField(null=True,blank=True, default='default.png', upload_to="profile/")
def __str__(self):
return f"{self.first_name ' ' self.last_name}"
def save(self, *args, **kawrgs):
super().save(*args, **kawrgs)
img = Image.open(self.passport.path)
if img.height > 300 or img.width > 300:
output_size = (300, 300)
img.thumbnail(output_size)
img.save(self.passport.path)
class Room(models.Model):
form_teacher = models.ForeignKey(Teacher, on_delete=models.CASCADE)
school_year = models.CharField(max_length=250)
level = models.CharField(max_length=250)
name = models.CharField(max_length=250)
def __str__(self):
return "[" self.level "] " self.level '-' self.name
class ClassStudent(models.Model):
classIns = models.ForeignKey(Room, on_delete=models.CASCADE)
student = models.ForeignKey(Student, on_delete=models.CASCADE)
def __str__(self):
return self.student.student_code
def get_present(self):
student = self.student
_class = self.classIns
try:
present = Attendance.objects.filter(
classIns=_class, student=student, type=1).count()
return present
except:
return 0
def get_tardy(self):
student = self.student
_class = self.classIns
try:
present = Attendance.objects.filter(
classIns=_class, student=student, type=2).count()
return present
except:
return 0
def get_absent(self):
student = self.student
_class = self.classIns
try:
present = Attendance.objects.filter(classIns= _class, student=student, type = 3).count()
return present
except:
return 0
class Attendance(models.Model):
classIns = models.ForeignKey(Room, on_delete=models.CASCADE, default=' ')
student = models.ForeignKey(Student, on_delete=models.CASCADE, default=' ')
attendance_date = models.DateField(default=' ')
type = models.CharField(max_length=250, choices=[(
'1', 'Present'), ('2', 'Tardy'), ('1', 'Absent')], default=' ')
date_updated = models.DateTimeField(auto_now=True)
def __str__(self):
return self.classIns.name " " self.student.student_code
views
# create a classroom
login_required()
def class_view(request):
form = ClassRoomForm()
if request.method == 'POST':
form = ClassRoomForm(request.POST)
if form.is_valid():
form.save()
name = form.cleaned_data.get('name')
messages.success(request, f'{name} was Successfully Added')
return redirect('classroom')
classes = Room.objects.all()
return render(request, 'school/class_view.html', {"form": form, 'classes': classes})
#show all the classroom created
@login_required
def class_detail(request,pk):
_class = Room.objects.filter(id=pk).first()
students = ClassStudent.objects.filter(classIns =_class).all()
print(students)
context = {
'class': _class,
'students': students
}
return render(request, "school/class_info.html", context)
#passes the form responsible for adding student to the classroom
@login_required
def save_class_student(request):
form = SaveClassStudent()
if request.method == 'POST':
form = SaveClassStudent(request.POST)
if form.is_valid():
form.save()
messages.success(request, "Student has been added successfully.")
redirect('class_detail')
return render(request, 'school/class_info.html', {'form': form})
forms
class ClassRoomForm(forms.ModelForm):
school_year = forms.CharField(max_length=250,help_text = "School Year Field is required.")
level = forms.CharField(max_length=250,help_text = "Level Field is required.")
name = forms.CharField(max_length=250,help_text = "Class Name Field is required.")
class Meta:
model = Room
fields = ('form_teacher', 'name', 'level', 'school_year')
class SaveClassStudent(forms.ModelForm):
classIns = forms.IntegerField()
student = forms.IntegerField()
class Meta:
model = ClassStudent
fields = ('classIns', 'student')
def clean_classIns(self):
cid = self.cleaned_data['classIns']
try:
classIns = Room.objects.get(id=cid)
return classIns
except:
raise forms.ValidationError("Class ID is Invalid.")
def clean_student(self):
student_id = self.cleaned_data['student']
_class = Room.objects.get(id=self.data.get('classIns'))
student = Student.objects.get(id=student_id)
try:
cs = ClassStudent.objects.get(classIns=_class, student=student)
if len(cs) > 0:
raise forms.ValidationError(
f"Student already exists in the Class List.")
except:
return student
HTML template for the form
{% extends 'school/dashboard.html' %}
{% load static %}
{% load widget_tweaks %}
{% load humanize %}
{% block title%}
<title>Class Information</title>
{% endblock %}
{% block page%}Class Info{% endblock %}
{% block card%} {%endblock%}
{% block table %}
<div >
<div >
<div >
<div >
<h4 >Class Information</h4>
<div >
<button type="button"
id='print_attendance_report'><i ></i> Print Attendance Report</button>
<a href="#addModal" data-bs-toggle="modal"> <button type="button" id='add_new'><i
></i> Add Student</button></a>
</div>
</div>
</div>
<div >
<div >
<fieldset id="class-details">
<legend>Class Details</legend>
<div >
<div >
<div >
<div >School Year:</div>
<div >
<p >{{ class.school_year }}</p>
</div>
</div>
</div>
<div >
<div >
<div >Level:</div>
<div >
<p >{{ class.level }}</p>
</div>
</div>
</div>
<div >
<div >
<div >Name:</div>
<div >
<p >{{ class.name }}</p>
</div>
</div>
</div>
<div >
<div >
<div >Faculty:</div>
<div >
<p >{{ class.form_teacher}}</p>
</div>
</div>
</div>
</div>
</fieldset>
<hr>
<fieldset>
<legend>Class Student List</legend>
<table id="student-list">
<colgroup>
<col width="10%">
<col width="25%">
<col width="25%">
<col width="10%">
<col width="10%">
<col width="10%">
<col width="10%">
</colgroup>
<thead>
<tr>
<th >#</th>
<th >Student Code</th>
<th >Student Name</th>
<th >Total Tardy</th>
<th >Total Absent</th>
<th >Total Present</th>
<th >Actions</th>
</tr>
</thead>
<tbody>
{% for student in students %}
<tr >
<td >{{ forloop.counter }}</td>
<td>{{ student.student.student_code }}</td>
<td>{{ student.student.first_name }} {{student.student.last_name }}</td>
<td >{{ student.get_present|intcomma }}</td>
<td >{{ student.get_tardy|intcomma }}</td>
<td >{{ student.get_absent|intcomma }}</td>
<td >
<button type="button"
data-id="{{ student.pk }}" title="Delete">
<i ></i>
</button>
</td>
</tr>
{% endfor %}
</tbody>
</table>
</fieldset>
</div>
</div>
</div>
</div>
{% endblock %}
{% block content%}
<!-- Modal -->
<div id="addModal" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1"
aria-labelledby="staticBackdropLabel" aria-hidden="true">
<div >
<div >
<div >
<h5 id="staticBackdropLabel">Add Student To Class</h5>
<button type="button" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div >
<form method="post">
{% csrf_token %}
<div >
<label >Student</label>
{% render_field form.student class ="form-control" %}
</div>
<div >
<button type="submit" >Place</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
{% endblock %}
CodePudding user response:
Here are a few recommendations. Firstly, within your forms.py
you're re-creating the existing fields and that's not necessary. For example:
class ClassRoomForm(forms.ModelForm):
# school_year = forms.CharField(max_length=250,help_text = "School Year Field is required.")
# level = forms.CharField(max_length=250,help_text = "Level Field is required.")
# name = forms.CharField(max_length=250,help_text = "Class Name Field is required.")
# There's no need to re-create the above since they're in the Room model already.
class Meta:
model = Room
fields = ('form_teacher', 'name', 'level', 'school_year')
# What you need to do is to use the widget attribute on the Class Meta to set the help_text and the max_length.
widgets = {
'name': forms.TextInput(attr={'class':'form-control'}, max_length=250, help_text='Class Name Field is required.'),
'level': forms.TextInput(attr={'class':'form-control'}, max_length=250, help_text='Level Field is required.'),
'school_year': forms.TextInput(attr={'class':'form-control'}, max_length=250, help_text='School Year Field is required.'),
}
You could take that approach for the other forms you have as well.
Secondly, since you mentioned that the save_class_student
method is passing the form, I'd suggest using {{ form.student }}
if you want to render the form field of the form you're passing to the template.
<form method="post">
{% csrf_token %}
...
<label >Student</label>
{{ form.student }}
...
</form>
However, I think you might want to pass the form from the class_detail
method since you want it to be displayed with the existing class information based on what you have in your template. With this, you could have the save_class_student
method to handle the post request
instead of trying to pass the form from there. For example:
@login_required
def class_detail(request,pk):
_class = Room.objects.filter(id=pk).first()
students = ClassStudent.objects.filter(classIns =_class).all()
# The classroom data: Initilizer
data = {
'classIns': _class # To set the classroom on the form since you'll be displaying on the student field.
}
form = SaveClassStudent(initial=data)
context = {
'class': _class,
'students': students,
'form': form,
}
return render(request, "school/class_info.html", context)
Then within the html
file, you can have the form's action calling the url
for the save_class_student
method.
<form method="post" action="{% url 'save_class_student url here' %}">
{% csrf_token %}
...
<label >Student</label>
{{ form.student }}
...
</form>