This commit is contained in:
sankalp committed 2025-01-08 21:15:45 +05:45
1 parent c738c1746a
commit 0504b881fb
30 files changed
+1296 -122

No files matched your search

+61 -3
View File
@@ -10,6 +10,8 @@ from app.models import (
Attendance,
Result,
Library,
Marksheet,
SubjectMark,
)
@@ -39,6 +41,7 @@ class StudentAdmin(BaseUserAdmin):
"last_name",
"father_name",
"mother_name",
"guardian_name",
"email",
"phone",
"course",
@@ -73,7 +76,7 @@ class StaffAdmin(BaseUserAdmin):
@admin.register(Course)
class CourseAdmin(admin.ModelAdmin):
list_display = ("id", "name", "course_type", "duration")
list_display = ("id", "name", "level", "course_type", "duration")
search_fields = ("name",)
list_filter = ("course_type",)
@@ -93,7 +96,7 @@ class SubjectAdmin(admin.ModelAdmin):
@admin.register(NewsEvent)
class NewsEventAdmin(admin.ModelAdmin):
list_display = ("id", "title", "type", "created_at")
list_display = ("id", "title", "summary", "type", "created_at")
search_fields = ("title", "summary")
list_filter = ("type", "created_at")
@@ -121,4 +124,59 @@ class ResultAdmin(admin.ModelAdmin):
@admin.register(Library)
class LibraryAdmin(admin.ModelAdmin):
list_display = ("book_name", "author", "publication_year")
list_display = ("book_name", "publication", "publication_year", "available")
class SubjectMarkInline(admin.TabularInline):
model = SubjectMark
extra = 1
fields = (
"subject",
"obtained_theory_marks",
"total_theory_marks",
"obtained_practical_marks",
"total_practical_marks",
"total_marks",
)
readonly_fields = ("total_marks",)
@admin.register(Marksheet)
class MarksheetAdmin(admin.ModelAdmin):
inlines = [SubjectMarkInline]
list_display = ["student", "course", "total_marks", "obtained_marks", "grade"]
readonly_fields = ["total_marks", "obtained_marks", "grade"]
# class SubjectMarkInline(admin.TabularInline):
# model = SubjectMark
# extra = 1
# fields = (
# "subject",
# "obtained_theory_marks",
# "total_theory_marks",
# "obtained_practical_marks",
# "total_practical_marks",
# "total_marks",
# )
# readonly_fields = ("total_marks",)
#
#
# @admin.register(Marksheet)
# class MarksheetAdmin(admin.ModelAdmin):
# list_display = ["student", "course", "total_marks", "obtained_marks", "grade"]
# list_filter = ["grade", "course"]
# search_fields = ["student__first_name", "student__last_name", "course__name"]
# readonly_fields = ["total_marks", "obtained_marks", "grade"]
# inlines = [SubjectMarkInline]
#
# fieldsets = (
# ("Student Information", {"fields": ("student", "course")}),
# (
# "Results",
# {
# "fields": ("total_marks", "obtained_marks", "grade"),
# "classes": ("collapse",),
# },
# ),
# )
+2 -2
View File
@@ -2,5 +2,5 @@ from django.apps import AppConfig
class AppConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'app'
default_auto_field = "django.db.models.BigAutoField"
name = "app"
@@ -0,0 +1,18 @@
# Generated by Django 5.1.4 on 2025-01-08 05:51
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('app', '0001_initial'),
]
operations = [
migrations.RenameField(
model_name='library',
old_name='author',
new_name='publication',
),
]
@@ -0,0 +1,72 @@
# Generated by Django 5.1.4 on 2025-01-08 07:33
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0002_rename_author_library_publication'),
]
operations = [
migrations.AlterField(
model_name='course',
name='level',
field=models.CharField(choices=[('basic', 'Basic'), ('primary', 'Primary'), ('secondary', 'Secondary'), ('vocational traning', 'Vocational Traning'), ('higher secondary', 'Higher Secondary'), ('graduation', 'Graduation'), ('post graduation', 'Post Graduation')], max_length=45),
),
migrations.AlterField(
model_name='staff',
name='position',
field=models.CharField(choices=[('lab Assistant', 'Lab Assistant'), ('librarian', 'Librarian'), ('accountant', 'Accountant'), ('guard', 'Guard'), ('driver', 'Driver'), ('helper', 'Helper'), ('cleaner', 'Cleaner')], max_length=255),
),
migrations.AlterField(
model_name='student',
name='father_occupation',
field=models.CharField(choices=[('agriculture', 'Agriculture'), ('banker', 'Banker'), ('business', 'Business'), ('doctor', 'Doctor'), ('farmer', 'Farmer'), ('fisherman', 'Fisherman'), ('public service', 'Public Service'), ('private service', 'Private Service'), ('shopkeeper', 'Shopkeeper'), ('driver', 'Driver'), ('worker', 'Worker'), ('N/A', 'N/A')], default='N/A', max_length=45),
),
migrations.AlterField(
model_name='student',
name='mother_occupation',
field=models.CharField(choices=[('agriculture', 'Agriculture'), ('banker', 'Banker'), ('business', 'Business'), ('doctor', 'Doctor'), ('farmer', 'Farmer'), ('fisherman', 'Fisherman'), ('public service', 'Public Service'), ('private service', 'Private Service'), ('shopkeeper', 'Shopkeeper'), ('driver', 'Driver'), ('houseWife', 'HouseWife'), ('worker', 'Worker'), ('N/A', 'N/A')], default='N/A', max_length=45),
),
migrations.AlterField(
model_name='student',
name='relationship_with_student',
field=models.CharField(choices=[('father', 'Father'), ('mother', 'Mother'), ('brother', 'Brother'), ('sister', 'Sister'), ('uncle', 'Uncle'), ('aunt', 'Aunt'), ('grandfather', 'Grandfather')], max_length=45),
),
migrations.CreateModel(
name='Certificate',
fields=[
('id', models.AutoField(primary_key=True, serialize=False)),
('title', models.CharField(max_length=255)),
('description', models.TextField(blank=True, null=True)),
('issue_date', models.DateField(auto_now_add=True)),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.course')),
('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='app.student')),
],
options={
'verbose_name': 'Certificate',
'verbose_name_plural': 'Certificate',
},
),
migrations.CreateModel(
name='Marksheet',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('marks_obtained', models.DecimalField(decimal_places=2, max_digits=5)),
('total_marks', models.DecimalField(decimal_places=2, max_digits=5)),
('grade', models.CharField(blank=True, max_length=2, null=True)),
('exam_date', models.DateField()),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='marksheets', to='app.course')),
('student', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='marksheets', to='app.student')),
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='marksheets', to='app.subject')),
],
options={
'verbose_name': 'Marksheet',
'verbose_name_plural': 'Marksheets',
'unique_together': {('student', 'course', 'subject')},
},
),
]
@@ -0,0 +1,34 @@
# Generated by Django 5.1.4 on 2025-01-08 07:39
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0003_alter_course_level_alter_staff_position_and_more'),
]
operations = [
migrations.AlterField(
model_name='marksheet',
name='exam_date',
field=models.DateField(help_text='Date of the examination'),
),
migrations.AlterField(
model_name='marksheet',
name='grade',
field=models.CharField(blank=True, choices=[('A+', 'Excellent'), ('A', 'Very Good'), ('B', 'Good'), ('C', 'Average'), ('D', 'Below Average'), ('F', 'Fail')], help_text='Grade assigned based on marks', max_length=2, null=True),
),
migrations.AlterField(
model_name='marksheet',
name='marks_obtained',
field=models.PositiveIntegerField(help_text='Marks obtained by the student', validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='marksheet',
name='total_marks',
field=models.PositiveIntegerField(help_text='Total marks for the subject', validators=[django.core.validators.MinValueValidator(1)]),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 5.1.4 on 2025-01-08 07:51
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0004_alter_marksheet_exam_date_alter_marksheet_grade_and_more'),
]
operations = [
migrations.AddField(
model_name='marksheet',
name='subj_result',
field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='app.result'),
),
]
@@ -0,0 +1,25 @@
# Generated by Django 5.1.4 on 2025-01-08 07:53
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
('app', '0005_marksheet_subj_result'),
]
operations = [
migrations.AlterUniqueTogether(
name='marksheet',
unique_together={('student', 'course')},
),
migrations.RemoveField(
model_name='marksheet',
name='exam_date',
),
migrations.RemoveField(
model_name='marksheet',
name='subject',
),
]
@@ -0,0 +1,46 @@
# Generated by Django 5.1.4 on 2025-01-08 08:29
import django.core.validators
import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0006_alter_marksheet_unique_together_and_more'),
]
operations = [
migrations.RemoveField(
model_name='marksheet',
name='marks_obtained',
),
migrations.RemoveField(
model_name='marksheet',
name='subj_result',
),
migrations.AddField(
model_name='marksheet',
name='obtained_marks',
field=models.PositiveIntegerField(default=0, help_text='Total marks obtained by the student', validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='marksheet',
name='total_marks',
field=models.PositiveIntegerField(help_text='Total marks for the course', validators=[django.core.validators.MinValueValidator(1)]),
),
migrations.CreateModel(
name='SubjectMark',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('marks_obtained', models.PositiveIntegerField(help_text='Marks obtained in this subject', validators=[django.core.validators.MinValueValidator(0)])),
('total_marks', models.PositiveIntegerField(help_text='Total marks for this subject', validators=[django.core.validators.MinValueValidator(1)])),
('marksheet', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subject_marks', to='app.marksheet')),
('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='subject_marks', to='app.subject')),
],
options={
'unique_together': {('marksheet', 'subject')},
},
),
]
@@ -0,0 +1,43 @@
# Generated by Django 5.1.4 on 2025-01-08 08:42
from decimal import Decimal
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0007_remove_marksheet_marks_obtained_and_more'),
]
operations = [
migrations.RemoveField(
model_name='subjectmark',
name='marks_obtained',
),
migrations.AddField(
model_name='subjectmark',
name='obtained_practical_marks',
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=5),
),
migrations.AddField(
model_name='subjectmark',
name='obtained_theory_marks',
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=5),
),
migrations.AddField(
model_name='subjectmark',
name='total_practical_marks',
field=models.DecimalField(decimal_places=2, default=Decimal('20.00'), max_digits=5),
),
migrations.AddField(
model_name='subjectmark',
name='total_theory_marks',
field=models.DecimalField(decimal_places=2, default=Decimal('80.00'), max_digits=5),
),
migrations.AlterField(
model_name='subjectmark',
name='total_marks',
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), editable=False, max_digits=5),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 5.1.4 on 2025-01-08 08:43
from decimal import Decimal
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0008_remove_subjectmark_marks_obtained_and_more'),
]
operations = [
migrations.AlterField(
model_name='subjectmark',
name='total_marks',
field=models.DecimalField(decimal_places=2, default=Decimal('0.00'), max_digits=5),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 5.1.4 on 2025-01-08 08:51
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0009_alter_subjectmark_total_marks'),
]
operations = [
migrations.AlterField(
model_name='marksheet',
name='total_marks',
field=models.PositiveIntegerField(default=0, help_text='Total marks for the course', validators=[django.core.validators.MinValueValidator(1)]),
),
]
@@ -0,0 +1,19 @@
# Generated by Django 5.1.4 on 2025-01-08 08:53
import django.core.validators
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0010_alter_marksheet_total_marks'),
]
operations = [
migrations.AlterField(
model_name='marksheet',
name='total_marks',
field=models.PositiveIntegerField(help_text='Total marks for the course', validators=[django.core.validators.MinValueValidator(1)]),
),
]
@@ -0,0 +1,25 @@
# Generated by Django 5.1.4 on 2025-01-08 09:01
import django.core.validators
from decimal import Decimal
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0011_alter_marksheet_total_marks'),
]
operations = [
migrations.AlterField(
model_name='marksheet',
name='obtained_marks',
field=models.PositiveIntegerField(default=Decimal('0.00'), editable=False, help_text='Total marks obtained by the student', validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='marksheet',
name='total_marks',
field=models.PositiveIntegerField(default=Decimal('0.00'), editable=False, help_text='Total marks for the course', validators=[django.core.validators.MinValueValidator(1)]),
),
]
@@ -0,0 +1,30 @@
# Generated by Django 5.1.4 on 2025-01-08 09:16
import django.core.validators
from decimal import Decimal
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0012_alter_marksheet_obtained_marks_and_more'),
]
operations = [
migrations.AlterField(
model_name='marksheet',
name='grade',
field=models.CharField(blank=True, choices=[('A+', 'Excellent'), ('A', 'Very Good'), ('B+', 'Good'), ('B', ''), ('C+', 'Average'), ('C', ''), ('D+', 'Below Average'), ('D', 'Fail')], help_text='Grade assigned based on marks', max_length=2, null=True),
),
migrations.AlterField(
model_name='marksheet',
name='obtained_marks',
field=models.PositiveIntegerField(default=Decimal('0.00'), help_text='Total marks obtained by the student', validators=[django.core.validators.MinValueValidator(0)]),
),
migrations.AlterField(
model_name='marksheet',
name='total_marks',
field=models.PositiveIntegerField(default=Decimal('0.00'), help_text='Total marks for the course', validators=[django.core.validators.MinValueValidator(1)]),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.4 on 2025-01-08 09:17
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0013_alter_marksheet_grade_alter_marksheet_obtained_marks_and_more'),
]
operations = [
migrations.AlterField(
model_name='marksheet',
name='grade',
field=models.CharField(blank=True, choices=[('A+', 'Excellent'), ('A', 'Very Good'), ('B+', 'Good'), ('B', 'G'), ('C+', 'Average'), ('C', 'A'), ('D+', 'Below Average'), ('D', 'Fail')], help_text='Grade assigned based on marks', max_length=2, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.4 on 2025-01-08 09:21
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0014_alter_marksheet_grade'),
]
operations = [
migrations.AlterField(
model_name='marksheet',
name='grade',
field=models.CharField(blank=True, choices=[('A+', 'Outstanding'), ('A', 'Excellent'), ('B+', 'Very Good'), ('B', 'Good'), ('C+', 'Above Average'), ('C', 'Average'), ('D', 'Below Average'), ('E', 'Fail')], help_text='Grade assigned based on marks', max_length=2, null=True),
),
]
@@ -0,0 +1,18 @@
# Generated by Django 5.1.4 on 2025-01-08 09:24
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('app', '0015_alter_marksheet_grade'),
]
operations = [
migrations.AlterField(
model_name='marksheet',
name='grade',
field=models.CharField(blank=True, choices=[('A+', 'A+'), ('A', 'A'), ('B+', 'B+'), ('B', 'B'), ('C+', 'C+'), ('C', 'C'), ('D', 'D'), ('E', 'E')], help_text='Grade assigned based on marks', max_length=2, null=True),
),
]
+259 -53
View File
@@ -5,6 +5,7 @@ from django.contrib.auth.hashers import make_password
import random
from decimal import Decimal
from datetime import time, timedelta, datetime
from django.core.validators import MinValueValidator, MaxValueValidator
# Abstract BaseUser Model
@@ -19,7 +20,6 @@ class BaseUser(models.Model):
)
username = models.CharField(max_length=255, unique=True, blank=True, null=True)
password = models.CharField(max_length=255)
address = models.CharField(max_length=255)
group = models.ManyToManyField(Group, blank=True)
user = models.OneToOneField(User, on_delete=models.CASCADE, null=True, blank=True)
@@ -42,7 +42,6 @@ class BaseUser(models.Model):
email=self.email,
first_name=self.first_name,
last_name=self.last_name,
address=self.address,
is_staff=True,
is_active=self.active_status,
password=self.password,
@@ -52,7 +51,6 @@ class BaseUser(models.Model):
self.user.email = self.email
self.user.first_name = self.first_name
self.user.last_name = self.last_name
self.user.address = self.address
self.user.is_active = self.active_status
self.user.is_staff = True
self.user.password = self.password
@@ -103,6 +101,7 @@ class Teacher(BaseUser):
class Student(BaseUser):
date_of_birth = models.DateField(blank=False)
gender = models.CharField(max_length=1, choices=[("M", "Male"), ("F", "Female")])
address = models.CharField(max_length=255)
course = models.ForeignKey("Course", on_delete=models.CASCADE)
academic_year = models.ForeignKey("AcademicYear", on_delete=models.CASCADE)
father_name = models.CharField(max_length=100)
@@ -111,17 +110,17 @@ class Student(BaseUser):
)
father_email = models.EmailField(blank=True, null=True)
father_occupation_choice = (
("Agriculture", "Agriculture"),
("Banker", "Banker"),
("Business", "Business"),
("Doctor", "Doctor"),
("Farmer", "Farmer"),
("Fisherman", "Fisherman"),
("Public Service", "Public Service"),
("Private Service", "Private Service"),
("Shopkeeper", "Shopkeeper"),
("Driver", "Driver"),
("Worker", "Worker"),
("agriculture", "Agriculture"),
("banker", "Banker"),
("business", "Business"),
("doctor", "Doctor"),
("farmer", "Farmer"),
("fisherman", "Fisherman"),
("public service", "Public Service"),
("private service", "Private Service"),
("shopkeeper", "Shopkeeper"),
("driver", "Driver"),
("worker", "Worker"),
("N/A", "N/A"),
)
father_occupation = models.CharField(
@@ -136,18 +135,18 @@ class Student(BaseUser):
)
mother_email = models.EmailField(blank=True, null=True)
mother_occupation_choice = (
("Agriculture", "Agriculture"),
("Banker", "Banker"),
("Business", "Business"),
("Doctor", "Doctor"),
("Farmer", "Farmer"),
("Fisherman", "Fisherman"),
("Public Service", "Public Service"),
("Private Service", "Private Service"),
("Shopkeeper", "Shopkeeper"),
("Driver", "Driver"),
("HouseWife", "HouseWife"),
("Worker", "Worker"),
("agriculture", "Agriculture"),
("banker", "Banker"),
("business", "Business"),
("doctor", "Doctor"),
("farmer", "Farmer"),
("fisherman", "Fisherman"),
("public service", "Public Service"),
("private service", "Private Service"),
("shopkeeper", "Shopkeeper"),
("driver", "Driver"),
("houseWife", "HouseWife"),
("worker", "Worker"),
("N/A", "N/A"),
)
mother_occupation = models.CharField(
@@ -159,13 +158,13 @@ class Student(BaseUser):
)
guardian_email = models.EmailField(blank=True, null=True)
relationship_choice = (
("Father", "Father"),
("Mother", "Mother"),
("Brother", "Brother"),
("Sister", "Sister"),
("Uncle", "Uncle"),
("Aunt", "Aunt"),
("Grandfather", "Grandfather"),
("father", "Father"),
("mother", "Mother"),
("brother", "Brother"),
("sister", "Sister"),
("uncle", "Uncle"),
("aunt", "Aunt"),
("grandfather", "Grandfather"),
)
relationship_with_student = models.CharField(
choices=relationship_choice, max_length=45
@@ -182,13 +181,13 @@ class Staff(BaseUser):
position = models.CharField(
max_length=255,
choices=[
("Lab Assistant", "Lab Assistant"),
("Librarian", "Librarian"),
("Accountant", "Accountant"),
("Guard", "Guard"),
("Driver", "Driver"),
("Helper", "Helper"),
("Cleaner", "Cleaner"),
("lab Assistant", "Lab Assistant"),
("librarian", "Librarian"),
("accountant", "Accountant"),
("guard", "Guard"),
("driver", "Driver"),
("helper", "Helper"),
("cleaner", "Cleaner"),
],
)
address = models.CharField(max_length=255)
@@ -211,13 +210,13 @@ class Staff(BaseUser):
class Course(models.Model):
name = models.CharField(max_length=100)
level_choice = (
("Basic", "Basic"),
("Primary", "Primary"),
("Secondary", "Secondary"),
("Vocational Traning", "Vocational Traning"),
("Higher Secondary", "Higher Secondary"),
("Graduation", "Graduation"),
("Post Graduation", "Post Graduation"),
("basic", "Basic"),
("primary", "Primary"),
("secondary", "Secondary"),
("vocational traning", "Vocational Traning"),
("higher secondary", "Higher Secondary"),
("graduation", "Graduation"),
("post graduation", "Post Graduation"),
)
level = models.CharField(choices=level_choice, max_length=45)
course_type = models.CharField(
@@ -239,7 +238,7 @@ class AcademicYear(models.Model):
year = models.CharField(max_length=255, unique=True)
def __str__(self):
return self.batch
return self.year
class Meta:
verbose_name = "Academic Year"
@@ -271,15 +270,17 @@ class Subject(models.Model):
# NewsEvent model
class NewsEvent(models.Model):
class NewsEventType(models.TextChoices):
NEWS = "news", "News"
EVENT = "event", "Event"
title = models.CharField(max_length=255)
summary = models.TextField()
type = models.CharField(
max_length=5, choices=[("news", "News"), ("event", "Event")]
)
type = models.CharField(max_length=5, choices=NewsEventType.choices)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return f"{self.title} ({self.get_type_display()})"
return f"{self.title} ({self.type})"
class Meta:
verbose_name = "News/Event"
@@ -337,7 +338,7 @@ class Library(models.Model):
category = models.CharField(max_length=255)
book_name = models.CharField(max_length=255)
description = models.CharField(max_length=255)
author = models.CharField(max_length=255)
publication = models.CharField(max_length=255)
publication_year = models.PositiveIntegerField()
quantity = models.PositiveIntegerField()
available = models.CharField(max_length=1, choices=[("Y", "Yes"), ("N", "NO")])
@@ -349,3 +350,208 @@ class Library(models.Model):
class Meta:
verbose_name = "Library"
verbose_name_plural = "Library"
class Certificate(models.Model):
id = models.AutoField(primary_key=True)
student = models.ForeignKey("Student", on_delete=models.CASCADE)
course = models.ForeignKey("Course", on_delete=models.CASCADE)
title = models.CharField(max_length=255)
description = models.TextField(blank=True, null=True)
issue_date = models.DateField(auto_now_add=True)
class Meta:
verbose_name = "Certificate"
verbose_name_plural = "Certificate"
class Marksheet(models.Model):
student = models.ForeignKey(
"Student", on_delete=models.CASCADE, related_name="marksheets"
)
course = models.ForeignKey(
"Course", on_delete=models.CASCADE, related_name="marksheets"
)
total_marks = models.PositiveIntegerField(
validators=[MinValueValidator(1)],
default=Decimal("0.00"),
help_text="Total marks for the course",
# editable=False,
)
obtained_marks = models.PositiveIntegerField(
validators=[MinValueValidator(0)],
default=Decimal("0.00"),
help_text="Total marks obtained by the student",
# editable=False,
)
grade = models.CharField(
max_length=2,
choices=[
# ("A+", "Outstanding"),
# ("A", "Excellent"),
# ("B+", "Very Good"),
# ("B", "Good"),
# ("C+", "Above Average"),
# ("C", "Average"),
# ("D", "Below Average"),
# ("E", "Fail"),
("A+", "A+"),
("A", "A"),
("B+", "B+"),
("B", "B"),
("C+", "C+"),
("C", "C"),
("D", "D"),
("E", "E"),
],
blank=True,
null=True,
help_text="Grade assigned based on marks",
)
class Meta:
verbose_name = "Marksheet"
verbose_name_plural = "Marksheets"
unique_together = ("student", "course")
def calculate_totals(self):
subject_marks = self.subject_marks.all()
total_marks = sum(
subject.total_practical_marks + subject.total_theory_marks
for subject in subject_marks
) or Decimal("0.00")
obtained_marks = sum(
subject.obtained_practical_marks + subject.obtained_theory_marks
for subject in subject_marks
) or Decimal("0.00")
return total_marks, obtained_marks
def save(self, *args, **kwargs):
if not self.pk:
super().save(*args, **kwargs)
self.total_marks, self.obtained_marks = self.calculate_totals()
if self.total_marks > 0:
percentage = (self.obtained_marks / self.total_marks) * 100
if percentage >= 90:
self.grade = "A+"
elif percentage >= 80:
self.grade = "A"
elif percentage >= 70:
self.grade = "B+"
elif percentage >= 60:
self.grade = "B"
elif percentage >= 50:
self.grade = "C+"
elif percentage >= 40:
self.grade = "C"
elif percentage >= 30:
self.grade = "D"
else:
self.grade = "E"
super().save(*args, **kwargs)
def __str__(self):
return f"Marksheet: {self.student.first_name} {self.student.last_name}"
class SubjectMark(models.Model):
marksheet = models.ForeignKey(
Marksheet, on_delete=models.CASCADE, related_name="subject_marks"
)
subject = models.ForeignKey(
"Subject", on_delete=models.CASCADE, related_name="subject_marks"
)
obtained_practical_marks = models.DecimalField(
max_digits=5, decimal_places=2, default=Decimal("0.00")
)
total_practical_marks = models.DecimalField(
max_digits=5, decimal_places=2, default=Decimal("20.00")
)
obtained_theory_marks = models.DecimalField(
max_digits=5, decimal_places=2, default=Decimal("0.00")
)
total_theory_marks = models.DecimalField(
max_digits=5, decimal_places=2, default=Decimal("80.00")
)
total_marks = models.DecimalField(
max_digits=5, decimal_places=2, default=Decimal("0.00")
)
def get_total(self):
return Decimal(str(self.obtained_practical_marks or 0)) + Decimal(
str(self.obtained_theory_marks or 0)
)
def save(self, *args, **kwargs):
self.total_marks = self.get_total()
super().save(*args, **kwargs)
self.marksheet.save()
class Meta:
unique_together = ("marksheet", "subject")
def __str__(self):
return f"{self.subject.name} - {self.marksheet.student.first_name}"
# class Marksheet(models.Model):
# student = models.ForeignKey(
# "Student", on_delete=models.CASCADE, related_name="marksheets"
# )
# course = models.ForeignKey(
# "Course", on_delete=models.CASCADE, related_name="marksheets"
# )
# subj_result = models.ForeignKey(
# "Result", on_delete=models.CASCADE, related_name="marksheets", null=True
# )
# marks_obtained = models.PositiveIntegerField(
# validators=[MinValueValidator(0)], help_text="Marks obtained by the student"
# )
# total_marks = models.PositiveIntegerField(
# validators=[MinValueValidator(1)], help_text="Total marks for the subject"
# )
# grade = models.CharField(
# max_length=2,
# choices=[
# ("A+", "Excellent"),
# ("A", "Very Good"),
# ("B", "Good"),
# ("C", "Average"),
# ("D", "Below Average"),
# ("F", "Fail"),
# ],
# blank=True,
# null=True,
# help_text="Grade assigned based on marks",
# )
#
# class Meta:
# verbose_name = "Marksheet"
# verbose_name_plural = "Marksheets"
# unique_together = ("student", "course")
#
# def save(self, *args, **kwargs):
# percentage = (self.marks_obtained / self.total_marks) * 100
# if percentage >= 90:
# self.grade = "A+"
# elif percentage >= 80:
# self.grade = "A"
# elif percentage >= 70:
# self.grade = "B"
# elif percentage >= 60:
# self.grade = "C"
# elif percentage >= 50:
# self.grade = "D"
# else:
# self.grade = "F"
#
# super().save(*args, **kwargs)
#
# def __str__(self):
# return f"Marksheet: {self.student.first_name} {self.student.last_name}"
+1
View File
@@ -4,4 +4,5 @@ from app import views
urlpatterns = [
path("dashboard", views.dashboard, name="dashboard"),
path("studentdashboard", views.studentdashboard, name="studentdashboard"),
path("marksheet", views.marksheet, name="marksheet"),
]
+51 -12
View File
@@ -1,32 +1,71 @@
from django.shortcuts import render, get_object_or_404
from django.shortcuts import render, redirect, get_object_or_404
from django.contrib.admin import site
from app.models import Student, NewsEvent, Subject
from app.models import (
Student,
NewsEvent,
AcademicYear,
Subject,
Teacher,
Staff,
Course,
Marksheet,
SubjectMark,
)
from django.contrib.auth.decorators import login_required
# Dashboard for admin
@login_required(login_url="login")
@login_required
def dashboard(request):
if not request.user.is_superuser:
return redirect("studentdashboard")
total_student = Student.objects.count()
total_teacher = Teacher.objects.count()
total_staff = Staff.objects.count()
total_course = Course.objects.count()
total_subjects = Subject.objects.count()
context = {
**site.each_context(request),
"title": "Dashboard",
# "breadcrumbs": [{"name": "Dashboard", "url": "dashboard"}],
"total_student": total_student,
"total_teacher": total_teacher,
"total_staff": total_staff,
"total_course": total_course,
"total_subjects": total_subjects,
}
return render(request, "dashboard.html", context)
# Student-specific dashboard
@login_required
def studentdashboard(request):
total_subject = Subject.objects.count()
student = Student.objects.get(user=request.user)
course_name = student.course.name
course = student.course
total_subjects = Subject.objects.filter(course=course).count()
subject = Subject.objects.filter(course=course)
context = {
**site.each_context(request),
"title": "Student Dashboard",
"total_subject": total_subject,
"course_name": course_name,
"subject": subject,
"total_subjects": total_subjects,
}
if request.user.is_authenticated:
news_events = NewsEvent.objects.all()
subjects = Subject.objects.all()
context["news_events"] = news_events
context["subjects"] = subjects
return render(request, "studentdashboard.html", context)
def marksheet(request):
marksheet = Marksheet.objects.first()
subject = SubjectMark.objects.filter(marksheet=marksheet)
context = {
**site.each_context(request),
"title": "Marksheet",
"marksheet": marksheet,
"subject": subject,
}
return render(request, "marksheet.html", context)
BIN
View File
Binary file not shown.

Before

Width:  |  Height:  |  Size: 24 KiB

+16 -33
View File
@@ -1,63 +1,43 @@
JAZZMIN_SETTINGS = {
# title of the window (Will default to current_admin_site.site_title if absent or None)
"site_title": "Student Management System Admin",
# Title on the login screen (19 chars max) (defaults to current_admin_site.site_header if absent or None)
"site_header": "Student Management System",
# Title on the brand (19 chars max) (defaults to current_admin_site.site_header if absent or None)
"site_brand": "SMS",
# Logo to use for your site, must be present in static files, used for brand on top left
"site_logo": "/src/img/logo2.png",
# CSS classes that are applied to the logo above
"site_logo_classes": "img-circle",
# Relative path to a favicon for your site, will default to site_logo if absent (ideally 32x32 px)
"site_icon": None,
# Welcome text on the login screen
"welcome_sign": "Welcome to the Student Management System",
# Copyright on the footer
"copyright": "ADDRSSS",
# theme
# The model admin to search from the search bar, search bar omitted if excluded
# "search_model": "auth.User",
# Field name on user model that contains avatar ImageField/URLField/Charfield or a callable that receives the user
"user_avatar": None,
"version": False,
############
# Top Menu #
############
# Links to put along the top menu
"topmenu_links": [
# Url that gets reversed (Permissions can be added)
{"name": "Home", "url": "admin:index", "permissions": ["auth.view_user"]},
# external url that opens in a new window (Permissions can be added)
# {"name": "Support", "url": "https://github.com/farridav/django-jazzmin/issues", "new_window": True},
# model admin to link to (Permissions checked against model)
# {"model": "auth.User"},
# App with dropdown menu to all its models pages (Permissions checked against models)
# {"app": "books"},
],
#############
# User Menu #
#############
# Additional links to include in the user menu on the top right ("app" url type is not allowed)
# "usermenu_links": [
# {"name": "Support", "url": "https://github.com/farridav/django-jazzmin/issues", "new_window": True},
@@ -67,30 +47,30 @@ JAZZMIN_SETTINGS = {
#############
# Side Menu #
#############
# Whether to display the side menu
"show_sidebar": True,
# Whether to aut expand the menu
"navigation_expanded": True,
# Hide these apps when generating side menu e.g (auth)
"hide_apps": [],
# Hide these models when generating side menu (e.g auth.user)
"hide_models": [],
# List of apps (and/or models) to base side menu ordering off of (does not need to contain all apps/models)
"order_with_respect_to": ["auth"],
"order_with_respect_to": ["auth", "dashboard"],
"custom_links": {
"app": [
{
"name": "Dashboard",
"url": "dashboard",
"icon": "fas fa-tachometer-alt",
},
]
},
#################
# Related Modal #
#################
# Use modals instead of popups
"related_modal_active": False,
#############
# UI Tweaks #
#############
@@ -99,7 +79,6 @@ JAZZMIN_SETTINGS = {
"custom_js": None,
# Whether to show the UI customizer on the sidebar
"show_ui_builder": False,
###############
# Change view #
###############
@@ -111,10 +90,14 @@ JAZZMIN_SETTINGS = {
# - carousel
"changeform_format": "horizontal_tabs",
# override change forms on a per modeladmin basis
"changeform_format_overrides": {"auth.user": "collapsible", "auth.group": "vertical_tabs"},
"changeform_format_overrides": {
"auth.user": "horizontal_tabs",
"auth.group": "vertical_tabs",
},
}
JAZZMIN_UI_TWEAKS = {
# "footer_fixed": True,
"theme": "lumen",
# "dark_mode_theme": "cyborg",
}
+1 -19
View File
@@ -25,26 +25,8 @@ urlpatterns = (
[
path("admin/", admin.site.urls),
path("", RedirectView.as_view(url="/admin/", permanent=False)),
path("", include("app.urls")),
]
+ static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
+ static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
)
# from django.contrib import admin
# from django.urls import path, include
#
# from django.conf import settings
# from django.conf.urls.static import static
#
#
# urlpatterns = (
# [
# path("admin/", admin.site.urls),
# path(
# "",
# include("app.urls"),
# ),
# ]
# + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
# + static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
# )
+152
View File
@@ -0,0 +1,152 @@
{% extends "admin/base_site.html" %}
{% block content %}
<h2 class="col-12">{{ title }}</h2>
<p class="col-12">Welcome</p>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<!--cards-->
<div class="row g-4 col-12">
<div class="col-12 col-md-6 col-lg-3">
<div class="card text-center p-3">
<h5>Total Students</h5>
<p class="fs-2">{{ total_student }}</p>
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="card text-center p-3">
<h5>Total Staff</h5>
<p class="fs-2">{{ total_staff }}</p>
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="card text-center p-3">
<h5>Total Teacher</h5>
<p class="fs-2">{{ total_teacher }}</p>
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="card text-center p-3">
<h5>Total Course</h5>
<p class="fs-2">{{ total_course }}</p>
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="card text-center p-3">
<h5>Total Subject</h5>
<p class="fs-2">{{ total_subjects }}</p>
</div>
</div>
</div>
<div class="row col-12">
<div class="col-12 col-md-6 col-lg-6">
<table class="text-center table table-bordered">
<thead class="table-dark">
<th>S.N</th>
<th>Name</th>
<th>Course</th>
<th>Academic Year</th>
</thead>
<tbody>
<td>1</td>
<td>hello</td>
<td>DCOM</td>
<td>2023</td>
</tbody>
</table>
</div>
<div class="col-12 col-md-6 col-lg-6">
<table class="text-center table table-bordered">
<thead class="table-dark">
<th>S.N</th>
<th>Name</th>
<th>Address</th>
<th>Phone No</th>
<th>Gmail</th>
</thead>
<tbody>
<tr>
<td>1</td>
<td>hello</td>
<td>kohalpur</td>
<td>9801230123</td>
<td>example@example.com</td>
</tr>
</tbody>
</table>
</div>
</div>
<!-- Pie Chart -->
<div class="row col-12 col-lg-6 chart-container">
<canvas id="pieChart"></canvas>
</div>
<!-- Bar Chart -->
<div class="row col-12 col-lg-6 chart-container">
<canvas id="barChart"></canvas>
</div>
<!-- Line Chart -->
<div class="row col-12 col-lg-6 chart-container">
<canvas id="lineChart"></canvas>
</div>
<script>
// Pie Chart
const pieCtx = document.getElementById("pieChart").getContext("2d");
new Chart(pieCtx, {
type: "pie",
data: {
labels: ["Category A", "Category B", "Category C"],
datasets: [
{
data: [30, 50, 20],
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"],
},
],
},
});
// Bar Chart
const barCtx = document.getElementById("barChart").getContext("2d");
new Chart(barCtx, {
type: "bar",
data: {
labels: ["Category A", "Category B", "Category C"],
datasets: [
{
label: "Values",
data: [30, 50, 20],
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56"],
},
],
},
options: {
scales: {
y: {
beginAtZero: true,
},
},
},
});
// Line Chart
const lineCtx = document.getElementById("lineChart").getContext("2d");
new Chart(lineCtx, {
type: "line",
data: {
labels: ["January", "February", "March", "April"],
datasets: [
{
label: "Values",
data: [10, 30, 20, 40],
borderColor: "#36A2EB",
fill: false,
},
],
},
options: {
scales: {
y: {
beginAtZero: true,
},
},
},
});
</script>
{% endblock %}
+144
View File
@@ -0,0 +1,144 @@
{% extends 'admin/base_site.html' %}
{% block content %}
<style>
body {
font-family: Arial, sans-serif;
margin: 20px;
}
.container {
width: 90%;
margin: auto;
padding: 20px;
border: 1px solid #000;
border-radius: 5px;
}
.header {
text-align: center;
}
.header h1,
.header h2,
.header p {
margin: 5px 0;
}
.header img {
width: 80px;
height: 80px;
}
.details {
margin-top: 20px;
line-height: 1.8;
}
.details span {
font-weight: bold;
}
table {
width: 100%;
border-collapse: collapse;
margin-top: 20px;
}
table,
th,
td {
border: 1px solid #000;
}
th,
td {
text-align: center;
padding: 8px;
}
th {
background-color: #f2f2f2;
}
.remarks {
margin-top: 20px;
text-align: left;
}
.btn-print {
display: block;
width: 100px;
margin: 20px auto;
padding: 10px;
background-color: #4CAF50;
color: #fff;
text-align: center;
text-decoration: none;
border-radius: 5px;
}
@media print {
.btn-print {
display: none;
}
}
</style>
</head>
<body>
<div class="container">
<div class="header">
<h1>SHREE SECONDARY SCHOOL</h1>
<p>Kohalpur-5, Banke</p>
<p>Estd. 281 BS</p>
<h2>GRADE - SHEET</h2>
</div>
<div class="details">
<p>
The grade(s) secured by: <span>{{ marksheet.student.first_name }} {{ marksheet.student.first_name }}</span>
</p>
<p>
Date of Birth: <span>
{{ marksheet.student.date_of_birth }}
<p>
In the Examination, {{ marksheet.student.course.name }} of {{ marksheet.student.academic_year }} are given below:
</p>
</div>
<table class="table table-bordered">
<thead>
<tr>
<th>S.N.</th>
<th>Subject</th>
<th>Theory</th>
<th>Practical</th>
<th>Total</th>
</tr>
</thead>
<tbody>
{% for subject in marksheet.subject_marks.all %}
<tr>
<td>{{ forloop.counter }}</td>
<td>{{ subject.subject.name }}</td>
<td>{{ subject.obtained_theory_marks }}</td>
<td>{{ subject.obtained_practical_marks }}</td>
<td>{{ subject.total_marks }}</td>
</tr>
{% endfor %}
<tr>
<td colspan="4" style="font-weight: bold; text-align: center;">Grand Total</td>
<td>{{ marksheet.obtained_marks }}</td>
</tr>
</tbody>
</table>
<div class="remarks">
<p>
Total Grade Point Average (Grade): <span>{{ marksheet.grade }}</span>
</p>
<p class="text-sm text-gray-600">
Percentage:
{{ marksheet.obtained_marks|div:marksheet.total_marks|mul:100|floatformat:2 }}%
</p>
</div>
<a href="#" class="btn-print" onclick="window.print();">Print PDF</a>
</div>
</body>
{% endblock %}
+77
View File
@@ -0,0 +1,77 @@
<!-- templates/marksheet/marksheet_detail.html -->
{% extends "admin/base_site.html" %}
{% block content %}
<div class="container mx-auto p-4">
<div class="bg-white shadow-lg rounded-lg p-6">
<!-- Student & Course Info -->
<div class="mb-6 border-b pb-4">
<h1 class="text-2xl font-bold mb-2">Student Marksheet</h1>
<div class="grid grid-cols-2 gap-4">
<div>
<p class="font-semibold">Student Name:</p>
<p>{{ marksheet.student.first_name }} {{ marksheet.student.last_name }}</p>
</div>
<div>
<p class="font-semibold">Course:</p>
<p>{{ marksheet.course.name }}</p>
</div>
</div>
</div>
<!-- Marks Table -->
<div class="overflow-x-auto">
<table class="w-full table-auto">
<thead>
<tr class="bg-gray-100">
<th class="px-4 py-2 text-left">Subject</th>
<th class="px-4 py-2 text-center">Theory Marks</th>
<th class="px-4 py-2 text-center">Practical Marks</th>
<th class="px-4 py-2 text-center">Total</th>
</tr>
</thead>
<tbody>
{% for subject_mark in marksheet.subject_marks.all %}
<tr class="border-b">
<td class="px-4 py-2">{{ subject_mark.subject.name }}</td>
<td class="px-4 py-2 text-center">
{{ subject_mark.obtained_theory_marks }}/{{
subject_mark.total_theory_marks }}
</td>
<td class="px-4 py-2 text-center">
{{ subject_mark.obtained_practical_marks }}/{{
subject_mark.total_practical_marks }}
</td>
<td class="px-4 py-2 text-center">
{{ subject_mark.total_marks }}/{{
subject_mark.total_practical_marks|add:subject_mark.total_theory_marks
}}
</td>
</tr>
{% endfor %}
</tbody>
<tfoot>
<tr class="bg-gray-50 font-bold">
<td class="px-4 py-2">Total</td>
<td class="px-4 py-2 text-center" colspan="2"></td>
<td class="px-4 py-2 text-center">{{ marksheet.obtained_marks }}/{{ marksheet.total_marks }}</td>
</tr>
</tfoot>
</table>
</div>
<!-- Final Grade -->
<div class="mt-6 text-center">
<div class="inline-block bg-blue-100 rounded-lg px-6 py-3">
<p class="text-lg font-semibold">
Final Grade:
<span class="text-2xl ml-2 {% if marksheet.grade == 'F' %}text-red-600{% else %}text-green-600{% endif %}">
{{ marksheet.grade }}
</span>
</p>
<!--<p class="text-sm text-gray-600">-->
<!-- Percentage:-->
<!--</p>-->
</div>
</div>
</div>
<a href="#" class="btn-print" onclick="window.print();">Print PDF</a>
</div>
{% endblock %}
+26
View File
@@ -0,0 +1,26 @@
{% extends "admin/base_site.html" %}
{% block content %}
<div class="container mx-auto p-4">
<h1 class="text-2xl font-bold mb-6">Student Marksheets</h1>
<div class="grid gap-4 md:grid-cols-2 lg:grid-cols-3">
{% for marksheet in marksheets %}
<div class="bg-white rounded-lg shadow-lg p-4">
<h2 class="text-xl font-semibold mb-2">{{ marksheet.student.first_name }} {{ marksheet.student.last_name }}</h2>
<p class="text-gray-600 mb-2">Course: {{ marksheet.course.name }}</p>
<div class="flex justify-between items-center mt-4">
<span class="text-sm">
Grade:
<span class="font-bold {% if marksheet.grade == 'F' %}text-red-600{% else %}text-green-600{% endif %}">
{{ marksheet.grade }}
</span>
</span>
<a href="{% url 'marksheetdetails' %}"
class="bg-blue-500 text-white px-4 py-2 rounded hover:bg-blue-600">View Details</a>
</div>
</div>
{% empty %}
<div class="col-span-full text-center py-8 text-gray-500">No marksheets available.</div>
{% endfor %}
</div>
</div>
{% endblock %}
View File
Whitespace-only changes.
+83
View File
@@ -0,0 +1,83 @@
{% extends "admin/base_site.html" %}
{% block content %}
<h2 class="col-12">{{ title }}</h2>
<p class="col-12">Welcome</p>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<div class="row g-4 col-12">
<div class="col-12 col-md-6 col-lg-3">
<div class="card text-center p-3">
<h5>Course</h5>
<p class="fs-2">{{ course_name }}</p>
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="card text-center p-3">
<h5>Current Semester</h5>
<p class="fs-2">5</p>
</div>
</div>
<div class="col-12 col-md-6 col-lg-3">
<div class="card text-center p-3">
<h5>Total Subject</h5>
<p class="fs-2">{{ total_subjects }}</p>
</div>
</div>
</div>
<!-- Subject Attendance Bar Chart -->
<div class="row col-12 col-lg-6 chart-container">
<canvas id="attendanceBarChart"></canvas>
</div>
<!-- Subject Results Bar Chart -->
<div class="row col-12 col-lg-6 chart-container">
<canvas id="resultBarChart"></canvas>
</div>
<script>
// Bar Chart for Subject Attendance
const attendanceCtx = document.getElementById("attendanceBarChart").getContext("2d");
new Chart(attendanceCtx, {
type: "bar",
data: {
labels: ["Math", "Science", "English", "History", "Geography"], // Example subject names
datasets: [
{
label: "Attendance Percentage",
data: [90, 80, 85, 75, 95], // Example attendance percentages for each subject
backgroundColor: ["#FF6384", "#36A2EB", "#FFCE56", "#4CAF50", "#FF8C00"],
},
],
},
options: {
scales: {
y: {
beginAtZero: true,
max: 100, // Percentage scale
},
},
},
});
// Bar Chart for Subject Results (Example)
const resultCtx = document.getElementById("resultBarChart").getContext("2d");
new Chart(resultCtx, {
type: "bar",
data: {
labels: ["Math", "Science", "English", "History", "Geography"], // Example subject names
datasets: [
{
label: "Results (Percentage)",
data: [88, 75, 80, 70, 92], // Example result percentages for each subject
backgroundColor: ["#FF5733", "#33FF57", "#3357FF", "#FF5733", "#FF8C00"],
},
],
},
options: {
scales: {
y: {
beginAtZero: true,
max: 100, // Percentage scale
},
},
},
});
</script>
{% endblock %}
View File
Whitespace-only changes.