From 24c5b68b6b83495b4bd2b5dd90e6c461420a6bc9 Mon Sep 17 00:00:00 2001 From: Zaki Benaissa Date: Wed, 31 Jan 2024 22:18:45 +0100 Subject: [PATCH 1/4] feat: add field 'gender' to User model --- accounts/migrations/0019_user_gender.py | 18 ++++++++++++++++++ accounts/models.py | 6 ++++++ 2 files changed, 24 insertions(+) create mode 100644 accounts/migrations/0019_user_gender.py diff --git a/accounts/migrations/0019_user_gender.py b/accounts/migrations/0019_user_gender.py new file mode 100644 index 0000000..e29f8a2 --- /dev/null +++ b/accounts/migrations/0019_user_gender.py @@ -0,0 +1,18 @@ +# Generated by Django 4.0.8 on 2024-01-31 21:17 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('accounts', '0018_rename_department_student_program'), + ] + + operations = [ + migrations.AddField( + model_name='user', + name='gender', + field=models.CharField(blank=True, choices=[('M', 'Male'), ('F', 'Female')], max_length=1, null=True), + ), + ] diff --git a/accounts/models.py b/accounts/models.py index 2b92825..cfe9692 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -55,11 +55,17 @@ class CustomUserManager(UserManager): return queryset +GENDERS_CHOICES = (("M", "Male"), ("F", "Female")) + + class User(AbstractUser): is_student = models.BooleanField(default=False) is_lecturer = models.BooleanField(default=False) is_parent = models.BooleanField(default=False) is_dep_head = models.BooleanField(default=False) + gender = models.CharField( + max_length=1, choices=GENDERS_CHOICES, blank=True, null=True + ) phone = models.CharField(max_length=60, blank=True, null=True) address = models.CharField(max_length=60, blank=True, null=True) picture = models.ImageField( From 571701d9577d8bd99ba0653760519a682459aaf3 Mon Sep 17 00:00:00 2001 From: Zaki Benaissa Date: Wed, 31 Jan 2024 22:33:12 +0100 Subject: [PATCH 2/4] feat: add gender field to StudentRegistrationForm --- accounts/forms.py | 12 +++++++++++- accounts/models.py | 6 ++---- templates/accounts/add_student.html | 1 + templates/registration/register.html | 4 ++++ 4 files changed, 18 insertions(+), 5 deletions(-) diff --git a/accounts/forms.py b/accounts/forms.py index 5780e0d..a10fae1 100644 --- a/accounts/forms.py +++ b/accounts/forms.py @@ -6,7 +6,7 @@ from django.contrib.auth.forms import ( ) from django.contrib.auth.forms import PasswordResetForm from course.models import Program -from .models import User, Student, Parent, RELATION_SHIP, LEVEL +from .models import User, Student, Parent, RELATION_SHIP, LEVEL, GENDERS class StaffAddForm(UserCreationForm): @@ -167,6 +167,15 @@ class StudentAddForm(UserCreationForm): label="Last name", ) + gender = forms.CharField( + widget=forms.Select( + choices=GENDERS, + attrs={ + "class": "browser-default custom-select form-control", + }, + ), + ) + level = forms.CharField( widget=forms.Select( choices=LEVEL, @@ -230,6 +239,7 @@ class StudentAddForm(UserCreationForm): user.is_student = True user.first_name = self.cleaned_data.get("first_name") user.last_name = self.cleaned_data.get("last_name") + user.gender = self.cleaned_data.get("gender") user.address = self.cleaned_data.get("address") user.phone = self.cleaned_data.get("phone") user.email = self.cleaned_data.get("email") diff --git a/accounts/models.py b/accounts/models.py index cfe9692..4090e6c 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -55,7 +55,7 @@ class CustomUserManager(UserManager): return queryset -GENDERS_CHOICES = (("M", "Male"), ("F", "Female")) +GENDERS = (("M", "Male"), ("F", "Female")) class User(AbstractUser): @@ -63,9 +63,7 @@ class User(AbstractUser): is_lecturer = models.BooleanField(default=False) is_parent = models.BooleanField(default=False) is_dep_head = models.BooleanField(default=False) - gender = models.CharField( - max_length=1, choices=GENDERS_CHOICES, blank=True, null=True - ) + gender = models.CharField(max_length=1, choices=GENDERS, blank=True, null=True) phone = models.CharField(max_length=60, blank=True, null=True) address = models.CharField(max_length=60, blank=True, null=True) picture = models.ImageField( diff --git a/templates/accounts/add_student.html b/templates/accounts/add_student.html index 2a00bdf..bfa580a 100644 --- a/templates/accounts/add_student.html +++ b/templates/accounts/add_student.html @@ -36,6 +36,7 @@
{{ form.first_name|as_crispy_field }} {{ form.last_name|as_crispy_field }} + {{ form.gender|as_crispy_field }} {{ form.email|as_crispy_field }} {{ form.address|as_crispy_field }} {{ form.phone|as_crispy_field }} diff --git a/templates/registration/register.html b/templates/registration/register.html index b8e605f..6e7ace1 100644 --- a/templates/registration/register.html +++ b/templates/registration/register.html @@ -53,6 +53,10 @@ {{ form.last_name }}
+
+ + {{ form.gender }} +
{{ form.level }} From 32efc848bca8d19b0f69096797c0670721085be6 Mon Sep 17 00:00:00 2001 From: Zaki Benaissa Date: Wed, 31 Jan 2024 22:51:37 +0100 Subject: [PATCH 3/4] feat: display students gender distribution in dashboard --- accounts/models.py | 7 +++++++ core/views.py | 5 ++++- templates/core/dashboard.html | 2 +- 3 files changed, 12 insertions(+), 2 deletions(-) diff --git a/accounts/models.py b/accounts/models.py index 4090e6c..23e5906 100644 --- a/accounts/models.py +++ b/accounts/models.py @@ -165,6 +165,13 @@ class Student(models.Model): def __str__(self): return self.student.get_full_name + @classmethod + def get_gender_count(cls): + males_count = Student.objects.filter(student__gender="M").count() + females_count = Student.objects.filter(student__gender="F").count() + + return {"M": males_count, "F": females_count} + def get_absolute_url(self): return reverse("profile_single", kwargs={"id": self.id}) diff --git a/core/views.py b/core/views.py index e2dceeb..241d290 100644 --- a/core/views.py +++ b/core/views.py @@ -4,7 +4,7 @@ from django.contrib.auth.decorators import login_required from django.conf import settings from accounts.decorators import admin_required, lecturer_required -from accounts.models import User +from accounts.models import User, Student from .forms import SessionForm, SemesterForm, NewsAndEventsForm from .models import * @@ -26,10 +26,13 @@ def home_view(request): @admin_required def dashboard_view(request): logs = ActivityLog.objects.all().order_by("-created_at")[:10] + gender_count = Student.get_gender_count() context = { "student_count": User.get_student_count(), "lecturer_count": User.get_lecturer_count(), "superuser_count": User.get_superuser_count(), + "males_count": gender_count["M"], + "females_count": gender_count["F"], "logs": logs, } return render(request, "core/dashboard.html", context) diff --git a/templates/core/dashboard.html b/templates/core/dashboard.html index d872b18..0232003 100644 --- a/templates/core/dashboard.html +++ b/templates/core/dashboard.html @@ -478,7 +478,7 @@ ], datasets: [{ label: "Students Gender Dataset", - data: [56, 44], + data: [{{ males_count }}, {{ females_count }}], backgroundColor: [ 'rgb(255, 99, 132)', 'rgb(54, 162, 235)' From a91d3b9e84f16b80023bf91428b9cb598ebf437f Mon Sep 17 00:00:00 2001 From: Zaki Benaissa Date: Wed, 31 Jan 2024 22:53:47 +0100 Subject: [PATCH 4/4] docs: remove 'display gender demographics in dashboard' from TODO.md --- TODO.md | 1 - 1 file changed, 1 deletion(-) diff --git a/TODO.md b/TODO.md index 34936bb..cd696de 100644 --- a/TODO.md +++ b/TODO.md @@ -10,7 +10,6 @@ - **Integrate the dashboard with dynamic/live data**: - Overall attendance - School demographics - - Gender - Lecturer qualification - Students' level - Students average grade per course: