Home > Mobile >  django form not showing in template to add data
django form not showing in template to add data

Time:06-10

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>
  • Related