From 33e8218e51376009308b3658796dc7bcaec14278 Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Tue, 18 Jul 2023 20:25:03 +0800 Subject: [PATCH] Automatically add subjects based on a .csv file --- ...lter_course_name_alter_course_shortname.py | 23 ++++++ stude/courses/models.py | 4 +- ..._semester_name_alter_semester_shortname.py | 23 ++++++ stude/semesters/models.py | 4 +- ...ubject_code_alter_subject_name_and_more.py | 76 +++++++++++++++++ stude/subjects/models.py | 82 +++++++++++++++++-- ...r_level_name_alter_year_level_shortname.py | 23 ++++++ stude/year_levels/models.py | 4 +- 8 files changed, 225 insertions(+), 14 deletions(-) create mode 100644 stude/courses/migrations/0003_alter_course_name_alter_course_shortname.py create mode 100644 stude/semesters/migrations/0002_alter_semester_name_alter_semester_shortname.py create mode 100644 stude/subjects/migrations/0002_alter_subject_code_alter_subject_name_and_more.py create mode 100644 stude/year_levels/migrations/0002_alter_year_level_name_alter_year_level_shortname.py diff --git a/stude/courses/migrations/0003_alter_course_name_alter_course_shortname.py b/stude/courses/migrations/0003_alter_course_name_alter_course_shortname.py new file mode 100644 index 0000000..72f807a --- /dev/null +++ b/stude/courses/migrations/0003_alter_course_name_alter_course_shortname.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.3 on 2023-07-18 10:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('courses', '0002_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='course', + name='name', + field=models.CharField(max_length=64, unique=True), + ), + migrations.AlterField( + model_name='course', + name='shortname', + field=models.CharField(max_length=16, unique=True), + ), + ] diff --git a/stude/courses/models.py b/stude/courses/models.py index a93f22f..e9e6fca 100644 --- a/stude/courses/models.py +++ b/stude/courses/models.py @@ -5,8 +5,8 @@ from django.db import models class Course(models.Model): - name = models.CharField(max_length=64) - shortname = models.CharField(max_length=16) + name = models.CharField(max_length=64, unique=True) + shortname = models.CharField(max_length=16, unique=True) subjects = models.ManyToManyField( 'subjects.Subject', related_name='SubjectCourse_course', through='subjects.SubjectCourse') diff --git a/stude/semesters/migrations/0002_alter_semester_name_alter_semester_shortname.py b/stude/semesters/migrations/0002_alter_semester_name_alter_semester_shortname.py new file mode 100644 index 0000000..2923f92 --- /dev/null +++ b/stude/semesters/migrations/0002_alter_semester_name_alter_semester_shortname.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.3 on 2023-07-18 10:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('semesters', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='semester', + name='name', + field=models.CharField(max_length=64, unique=True), + ), + migrations.AlterField( + model_name='semester', + name='shortname', + field=models.CharField(max_length=16, unique=True), + ), + ] diff --git a/stude/semesters/models.py b/stude/semesters/models.py index 162c5b8..93ca4b3 100644 --- a/stude/semesters/models.py +++ b/stude/semesters/models.py @@ -6,8 +6,8 @@ from django.dispatch import receiver class Semester(models.Model): - name = models.CharField(max_length=64) - shortname = models.CharField(max_length=16) + name = models.CharField(max_length=64, unique=True) + shortname = models.CharField(max_length=16, unique=True) def __str__(self): return self.name diff --git a/stude/subjects/migrations/0002_alter_subject_code_alter_subject_name_and_more.py b/stude/subjects/migrations/0002_alter_subject_code_alter_subject_name_and_more.py new file mode 100644 index 0000000..a55567d --- /dev/null +++ b/stude/subjects/migrations/0002_alter_subject_code_alter_subject_name_and_more.py @@ -0,0 +1,76 @@ +# Generated by Django 4.2.3 on 2023-07-18 10:28 + +from django.conf import settings +from django.db import migrations, models +import django.db.models.deletion + + +class Migration(migrations.Migration): + + dependencies = [ + ('year_levels', '0002_alter_year_level_name_alter_year_level_shortname'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('courses', '0003_alter_course_name_alter_course_shortname'), + ('semesters', '0002_alter_semester_name_alter_semester_shortname'), + ('subjects', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='subject', + name='code', + field=models.CharField(max_length=16, unique=True), + ), + migrations.AlterField( + model_name='subject', + name='name', + field=models.CharField(max_length=64, unique=True), + ), + migrations.AlterField( + model_name='subject', + name='students', + field=models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL), + ), + migrations.AlterField( + model_name='subjectcourse', + name='course', + field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.course', to_field='name'), + ), + migrations.AlterField( + model_name='subjectcourse', + name='subject', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name'), + ), + migrations.AlterField( + model_name='subjectsemester', + name='semester', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='semesters.semester', to_field='name'), + ), + migrations.AlterField( + model_name='subjectsemester', + name='subject', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name'), + ), + migrations.AlterField( + model_name='subjectyearlevel', + name='subject', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject', to_field='name'), + ), + migrations.AlterField( + model_name='subjectyearlevel', + name='year_level', + field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='year_levels.year_level', to_field='name'), + ), + migrations.AlterUniqueTogether( + name='subjectcourse', + unique_together={('subject', 'course')}, + ), + migrations.AlterUniqueTogether( + name='subjectsemester', + unique_together={('subject', 'semester')}, + ), + migrations.AlterUniqueTogether( + name='subjectyearlevel', + unique_together={('subject', 'year_level')}, + ), + ] diff --git a/stude/subjects/models.py b/stude/subjects/models.py index 964c823..de3a294 100644 --- a/stude/subjects/models.py +++ b/stude/subjects/models.py @@ -1,12 +1,19 @@ + +import os +import csv +from django.conf import settings from django.db import models +from django.db.models.signals import post_migrate +from django.dispatch import receiver +from courses.models import Course from year_levels.models import Year_Level from semesters.models import Semester # Create your models here. class Subject(models.Model): - name = models.CharField(max_length=64) - code = models.CharField(max_length=16) + name = models.CharField(max_length=64, unique=True) + code = models.CharField(max_length=16, unique=True) courses = models.ManyToManyField( 'courses.Course', through='subjects.SubjectCourse', related_name='SubjectCourse_subject') students = models.ManyToManyField( @@ -23,9 +30,10 @@ class Subject(models.Model): class SubjectCourse(models.Model): - subject = models.ForeignKey('subjects.Subject', on_delete=models.CASCADE) + subject = models.ForeignKey( + 'subjects.Subject', on_delete=models.CASCADE, to_field='name') course = models.ForeignKey( - 'courses.Course', on_delete=models.CASCADE, null=True) + 'courses.Course', on_delete=models.CASCADE, null=True, to_field='name') def __str__(self): return f'Subject={self.subject.name}, Course={self.course.name}' @@ -36,9 +44,9 @@ class SubjectCourse(models.Model): class SubjectYearLevel(models.Model): subject = models.ForeignKey( - 'subjects.Subject', on_delete=models.CASCADE) + 'subjects.Subject', on_delete=models.CASCADE, to_field='name') year_level = models.ForeignKey( - 'year_levels.Year_Level', on_delete=models.CASCADE) + 'year_levels.Year_Level', on_delete=models.CASCADE, to_field='name') def __str__(self): return f'Subject={self.subject.name}, Year Level={self.year_level.name}' @@ -49,12 +57,70 @@ class SubjectYearLevel(models.Model): class SubjectSemester(models.Model): subject = models.ForeignKey( - 'subjects.Subject', on_delete=models.CASCADE) + 'subjects.Subject', on_delete=models.CASCADE, to_field='name') semester = models.ForeignKey( - 'semesters.Semester', on_delete=models.CASCADE) + 'semesters.Semester', on_delete=models.CASCADE, to_field='name') def __str__(self): return f'Subject={self.subject.name}, Semester={self.semester.name}' class Meta: unique_together = [['subject', 'semester']] + + +# Create subjects on initial migrate +@receiver(post_migrate) +def populate_subjects(sender, **kwargs): + if sender.name == 'subjects': + root_path = os.path.join(settings.MEDIA_ROOT, 'records') + csv_files = [f for f in os.listdir(root_path) if f.endswith('.csv')] + + for csv_file in csv_files: + csv_file_path = os.path.join(root_path, csv_file) + # Filename contains course of subjects + filename = os.path.splitext(csv_file)[0] + print('Reading subjects from', filename) + with open(csv_file_path, newline='') as csvfile: + + reader = csv.reader(csvfile) + next(reader) # Skip the header row + + for row in reader: + if not any(row): + continue + + # Get subject information + year_term = row[0].split('-') + subject_year_level = year_term[0].strip() + subject_semester = year_term[1].strip() + subject_code = row[1] + subject_name = row[2] + + # Skip ROTC/NSTP Subjects + if (subject_code is 'NSTP102,ROTC/CWTS/LTS 2'): + continue + + # Skip Practicum Subjects + if ('PRACTICUM' in subject_name): + continue + + # Skip Capstone Subjects + if ('CAPSTONE' in subject_name): + continue + + course = Course.objects.filter( + name=filename).first() + year_level = Year_Level.objects.filter( + name=subject_year_level).first() + semester = Semester.objects.filter( + name=subject_semester).first() + # Create the subject instance or get if it already exists + SUBJECT = Subject.objects.get_or_create( + name=subject_name, + code=subject_code, + + ) + # Set the course, year level, and semester of the subject + SUBJECT[0].courses.set([course]) + SUBJECT[0].year_levels.set([year_level]) + SUBJECT[0].semesters.set([semester]) diff --git a/stude/year_levels/migrations/0002_alter_year_level_name_alter_year_level_shortname.py b/stude/year_levels/migrations/0002_alter_year_level_name_alter_year_level_shortname.py new file mode 100644 index 0000000..2173bee --- /dev/null +++ b/stude/year_levels/migrations/0002_alter_year_level_name_alter_year_level_shortname.py @@ -0,0 +1,23 @@ +# Generated by Django 4.2.3 on 2023-07-18 10:28 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('year_levels', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='year_level', + name='name', + field=models.CharField(max_length=64, unique=True), + ), + migrations.AlterField( + model_name='year_level', + name='shortname', + field=models.CharField(max_length=16, unique=True), + ), + ] diff --git a/stude/year_levels/models.py b/stude/year_levels/models.py index c67c7d1..9f89894 100644 --- a/stude/year_levels/models.py +++ b/stude/year_levels/models.py @@ -6,8 +6,8 @@ from django.dispatch import receiver class Year_Level(models.Model): - name = models.CharField(max_length=64) - shortname = models.CharField(max_length=16) + name = models.CharField(max_length=64, unique=True) + shortname = models.CharField(max_length=16, unique=True) def __str__(self): return self.name