From 0eff07a1ae9aae0da12f7df3fbf4f43415c6985d Mon Sep 17 00:00:00 2001 From: Keannu Bernasol Date: Wed, 26 Jul 2023 12:14:19 +0800 Subject: [PATCH] Overhauled the entire subjects app to be more simplified and to remove anomalies when filtering in queries --- stude/accounts/migrations/0001_initial.py | 9 +- stude/accounts/migrations/0002_initial.py | 25 +---- stude/accounts/models.py | 2 +- stude/courses/migrations/0001_initial.py | 6 +- stude/courses/migrations/0002_initial.py | 21 ---- ...lter_course_name_alter_course_shortname.py | 23 ---- stude/courses/models.py | 2 - stude/landmarks/migrations/0001_initial.py | 2 +- stude/semesters/migrations/0001_initial.py | 6 +- ..._semester_name_alter_semester_shortname.py | 23 ---- .../student_status/migrations/0001_initial.py | 4 +- .../student_status/migrations/0002_initial.py | 4 +- stude/study_groups/migrations/0001_initial.py | 2 +- stude/study_groups/views.py | 13 +-- .../migrations/0001_initial.py | 4 +- stude/subjects/admin.py | 14 +-- stude/subjects/migrations/0001_initial.py | 58 +++------- ...ubject_code_alter_subject_name_and_more.py | 76 ------------- ...ctcode_remove_subject_code_subject_code.py | 29 ----- .../0004_rename_code_subject_codes.py | 18 ---- stude/subjects/models.py | 102 ++++++------------ stude/subjects/serializers.py | 30 ++++-- stude/subjects/views.py | 27 +++-- stude/year_levels/migrations/0001_initial.py | 6 +- ...r_level_name_alter_year_level_shortname.py | 23 ---- 25 files changed, 122 insertions(+), 407 deletions(-) delete mode 100644 stude/courses/migrations/0002_initial.py delete mode 100644 stude/courses/migrations/0003_alter_course_name_alter_course_shortname.py delete mode 100644 stude/semesters/migrations/0002_alter_semester_name_alter_semester_shortname.py delete mode 100644 stude/subjects/migrations/0002_alter_subject_code_alter_subject_name_and_more.py delete mode 100644 stude/subjects/migrations/0003_subjectcode_remove_subject_code_subject_code.py delete mode 100644 stude/subjects/migrations/0004_rename_code_subject_codes.py delete mode 100644 stude/year_levels/migrations/0002_alter_year_level_name_alter_year_level_shortname.py diff --git a/stude/accounts/migrations/0001_initial.py b/stude/accounts/migrations/0001_initial.py index fedcb98..4836bd0 100644 --- a/stude/accounts/migrations/0001_initial.py +++ b/stude/accounts/migrations/0001_initial.py @@ -1,9 +1,10 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 import accounts.models import django.contrib.auth.models import django.contrib.auth.validators from django.db import migrations, models +import django.db.models.deletion import django.utils.timezone @@ -12,6 +13,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('courses', '0001_initial'), + ('auth', '0012_alter_user_first_name_max_length'), + ('semesters', '0001_initial'), ] operations = [ @@ -34,6 +38,9 @@ class Migration(migrations.Migration): ('is_banned', models.BooleanField(default=False)), ('student_id_number', models.CharField(max_length=16, validators=[accounts.models.validate_student_id])), ('avatar', models.ImageField(null=True, upload_to=accounts.models.CustomUser._get_upload_to)), + ('course', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='courses.course')), + ('groups', models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups')), + ('semester', models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='semesters.semester')), ], options={ 'verbose_name': 'user', diff --git a/stude/accounts/migrations/0002_initial.py b/stude/accounts/migrations/0002_initial.py index c0e486a..6f57ff3 100644 --- a/stude/accounts/migrations/0002_initial.py +++ b/stude/accounts/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 from django.db import migrations, models import django.db.models.deletion @@ -9,34 +9,17 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('auth', '0012_alter_user_first_name_max_length'), ('year_levels', '0001_initial'), - ('accounts', '0001_initial'), - ('semesters', '0001_initial'), - ('courses', '0002_initial'), ('subjects', '0001_initial'), + ('accounts', '0001_initial'), + ('auth', '0012_alter_user_first_name_max_length'), ] operations = [ - migrations.AddField( - model_name='customuser', - name='course', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='courses.course'), - ), - migrations.AddField( - model_name='customuser', - name='groups', - field=models.ManyToManyField(blank=True, help_text='The groups this user belongs to. A user will get all permissions granted to each of their groups.', related_name='user_set', related_query_name='user', to='auth.group', verbose_name='groups'), - ), - migrations.AddField( - model_name='customuser', - name='semester', - field=models.ForeignKey(null=True, on_delete=django.db.models.deletion.SET_NULL, to='semesters.semester'), - ), migrations.AddField( model_name='customuser', name='subjects', - field=models.ManyToManyField(to='subjects.subject'), + field=models.ManyToManyField(to='subjects.subjectinstance'), ), migrations.AddField( model_name='customuser', diff --git a/stude/accounts/models.py b/stude/accounts/models.py index 296ac68..5edfbda 100644 --- a/stude/accounts/models.py +++ b/stude/accounts/models.py @@ -53,7 +53,7 @@ class CustomUser(AbstractUser): on_delete=models.SET_NULL, null=True ) - subjects = models.ManyToManyField('subjects.Subject') + subjects = models.ManyToManyField('subjects.SubjectInstance') @property def full_name(self): diff --git a/stude/courses/migrations/0001_initial.py b/stude/courses/migrations/0001_initial.py index e6da990..95ddace 100644 --- a/stude/courses/migrations/0001_initial.py +++ b/stude/courses/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 from django.db import migrations, models @@ -15,8 +15,8 @@ class Migration(migrations.Migration): name='Course', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('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)), ], ), ] diff --git a/stude/courses/migrations/0002_initial.py b/stude/courses/migrations/0002_initial.py deleted file mode 100644 index a4f4500..0000000 --- a/stude/courses/migrations/0002_initial.py +++ /dev/null @@ -1,21 +0,0 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - initial = True - - dependencies = [ - ('courses', '0001_initial'), - ('subjects', '0001_initial'), - ] - - operations = [ - migrations.AddField( - model_name='course', - name='subjects', - field=models.ManyToManyField(related_name='SubjectCourse_course', through='subjects.SubjectCourse', to='subjects.subject'), - ), - ] 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 deleted file mode 100644 index 72f807a..0000000 --- a/stude/courses/migrations/0003_alter_course_name_alter_course_shortname.py +++ /dev/null @@ -1,23 +0,0 @@ -# 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 622a816..8b2c262 100644 --- a/stude/courses/models.py +++ b/stude/courses/models.py @@ -9,8 +9,6 @@ from django.db import models class Course(models.Model): 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') def __str__(self): return self.name diff --git a/stude/landmarks/migrations/0001_initial.py b/stude/landmarks/migrations/0001_initial.py index 0018b9c..ec11adf 100644 --- a/stude/landmarks/migrations/0001_initial.py +++ b/stude/landmarks/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 import django.contrib.gis.db.models.fields from django.db import migrations, models diff --git a/stude/semesters/migrations/0001_initial.py b/stude/semesters/migrations/0001_initial.py index bc479f6..4d2fd50 100644 --- a/stude/semesters/migrations/0001_initial.py +++ b/stude/semesters/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 from django.db import migrations, models @@ -15,8 +15,8 @@ class Migration(migrations.Migration): name='Semester', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('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)), ], ), ] 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 deleted file mode 100644 index 2923f92..0000000 --- a/stude/semesters/migrations/0002_alter_semester_name_alter_semester_shortname.py +++ /dev/null @@ -1,23 +0,0 @@ -# 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/student_status/migrations/0001_initial.py b/stude/student_status/migrations/0001_initial.py index dc438b5..586e080 100644 --- a/stude/student_status/migrations/0001_initial.py +++ b/stude/student_status/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 from django.conf import settings import django.contrib.gis.db.models.fields @@ -11,8 +11,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('accounts', '0002_initial'), ('landmarks', '0001_initial'), + ('accounts', '0002_initial'), ] operations = [ diff --git a/stude/student_status/migrations/0002_initial.py b/stude/student_status/migrations/0002_initial.py index 54f0607..954ef5b 100644 --- a/stude/student_status/migrations/0002_initial.py +++ b/stude/student_status/migrations/0002_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 from django.db import migrations, models import django.db.models.deletion @@ -9,8 +9,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('study_groups', '0001_initial'), ('student_status', '0001_initial'), + ('study_groups', '0001_initial'), ('subjects', '0001_initial'), ] diff --git a/stude/study_groups/migrations/0001_initial.py b/stude/study_groups/migrations/0001_initial.py index 5f1af60..4cde52a 100644 --- a/stude/study_groups/migrations/0001_initial.py +++ b/stude/study_groups/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 import django.contrib.gis.db.models.fields from django.db import migrations, models diff --git a/stude/study_groups/views.py b/stude/study_groups/views.py index 6916fd1..4d7a65b 100644 --- a/stude/study_groups/views.py +++ b/stude/study_groups/views.py @@ -4,7 +4,7 @@ from rest_framework.exceptions import PermissionDenied from rest_framework.permissions import IsAuthenticated from .serializers import StudyGroupSerializer from .models import StudyGroup -from subjects.models import SubjectCourse +from subjects.models import SubjectInstance # Create your views here. @@ -24,15 +24,16 @@ class StudyGroupListView(generics.ListAPIView): # Get the user's course user_course = user.course print(user_course) - # Get subject ids related to the user's course through SubjectCourse - subject_ids = SubjectCourse.objects.filter( + + # Get subject names related to the user's course + subject_names = SubjectInstance.objects.filter( course=user_course ).values_list('subject', flat=True) - print(subject_ids) + print(subject_names) - # Now fetch the StudyGroups with the subjects from the obtained subject_ids - studygroups = StudyGroup.objects.filter(subject_id__in=subject_ids) + # Now fetch the StudyGroups with the matching subject names + studygroups = StudyGroup.objects.filter(subject_name__in=subject_names) return studygroups diff --git a/stude/studygroup_messages/migrations/0001_initial.py b/stude/studygroup_messages/migrations/0001_initial.py index 8dc01db..d2b9301 100644 --- a/stude/studygroup_messages/migrations/0001_initial.py +++ b/stude/studygroup_messages/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 from django.conf import settings from django.db import migrations, models @@ -10,8 +10,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('study_groups', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), ] operations = [ diff --git a/stude/subjects/admin.py b/stude/subjects/admin.py index 77d9077..de056f7 100644 --- a/stude/subjects/admin.py +++ b/stude/subjects/admin.py @@ -1,12 +1,6 @@ from django.contrib import admin -from .models import Subject, SubjectCourse, SubjectSemester, SubjectYearLevel +from .models import Subject, SubjectCode, SubjectInstance - -class SubjectAdmin(admin.ModelAdmin): - filter_horizontal = ['courses'] - - -admin.site.register(Subject, SubjectAdmin) -admin.site.register(SubjectCourse) -admin.site.register(SubjectSemester) -admin.site.register(SubjectYearLevel) +admin.site.register(Subject) +admin.site.register(SubjectInstance) +admin.site.register(SubjectCode) diff --git a/stude/subjects/migrations/0001_initial.py b/stude/subjects/migrations/0001_initial.py index c83d0ea..c654efa 100644 --- a/stude/subjects/migrations/0001_initial.py +++ b/stude/subjects/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 from django.conf import settings from django.db import migrations, models @@ -10,10 +10,10 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('semesters', '0001_initial'), - migrations.swappable_dependency(settings.AUTH_USER_MODEL), ('courses', '0001_initial'), ('year_levels', '0001_initial'), + migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('semesters', '0001_initial'), ] operations = [ @@ -21,52 +21,26 @@ class Migration(migrations.Migration): name='Subject', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=64)), - ('code', models.CharField(max_length=16)), + ('name', models.CharField(max_length=64, unique=True)), ], ), migrations.CreateModel( - name='SubjectYearLevel', + name='SubjectCode', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.CharField(max_length=16, unique=True)), + ], + ), + migrations.CreateModel( + name='SubjectInstance', + fields=[ + ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), + ('code', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subjectcode')), + ('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='courses.course')), + ('semester', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='semesters.semester')), + ('students', models.ManyToManyField(blank=True, to=settings.AUTH_USER_MODEL)), ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')), ('year_level', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='year_levels.year_level')), ], ), - migrations.CreateModel( - name='SubjectSemester', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('semester', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='semesters.semester')), - ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')), - ], - ), - migrations.CreateModel( - name='SubjectCourse', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('course', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, to='courses.course')), - ('subject', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, to='subjects.subject')), - ], - ), - migrations.AddField( - model_name='subject', - name='courses', - field=models.ManyToManyField(related_name='SubjectCourse_subject', through='subjects.SubjectCourse', to='courses.course'), - ), - migrations.AddField( - model_name='subject', - name='semesters', - field=models.ManyToManyField(related_name='SubjectSemester_subject', through='subjects.SubjectSemester', to='semesters.semester'), - ), - migrations.AddField( - model_name='subject', - name='students', - field=models.ManyToManyField(to=settings.AUTH_USER_MODEL), - ), - migrations.AddField( - model_name='subject', - name='year_levels', - field=models.ManyToManyField(related_name='SubjectYearLevel_subject', through='subjects.SubjectYearLevel', to='year_levels.year_level'), - ), ] 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 deleted file mode 100644 index a55567d..0000000 --- a/stude/subjects/migrations/0002_alter_subject_code_alter_subject_name_and_more.py +++ /dev/null @@ -1,76 +0,0 @@ -# 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/migrations/0003_subjectcode_remove_subject_code_subject_code.py b/stude/subjects/migrations/0003_subjectcode_remove_subject_code_subject_code.py deleted file mode 100644 index f63db3e..0000000 --- a/stude/subjects/migrations/0003_subjectcode_remove_subject_code_subject_code.py +++ /dev/null @@ -1,29 +0,0 @@ -# Generated by Django 4.2.3 on 2023-07-19 07:04 - -from django.db import migrations, models - - -class Migration(migrations.Migration): - - dependencies = [ - ('subjects', '0002_alter_subject_code_alter_subject_name_and_more'), - ] - - operations = [ - migrations.CreateModel( - name='SubjectCode', - fields=[ - ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('code', models.CharField(max_length=16, unique=True)), - ], - ), - migrations.RemoveField( - model_name='subject', - name='code', - ), - migrations.AddField( - model_name='subject', - name='code', - field=models.ManyToManyField(to='subjects.subjectcode'), - ), - ] diff --git a/stude/subjects/migrations/0004_rename_code_subject_codes.py b/stude/subjects/migrations/0004_rename_code_subject_codes.py deleted file mode 100644 index 6aa4990..0000000 --- a/stude/subjects/migrations/0004_rename_code_subject_codes.py +++ /dev/null @@ -1,18 +0,0 @@ -# Generated by Django 4.2.3 on 2023-07-19 07:09 - -from django.db import migrations - - -class Migration(migrations.Migration): - - dependencies = [ - ('subjects', '0003_subjectcode_remove_subject_code_subject_code'), - ] - - operations = [ - migrations.RenameField( - model_name='subject', - old_name='code', - new_name='codes', - ), - ] diff --git a/stude/subjects/models.py b/stude/subjects/models.py index c99d7b1..e44217a 100644 --- a/stude/subjects/models.py +++ b/stude/subjects/models.py @@ -6,29 +6,16 @@ from django.db import models from django.db.models.signals import post_migrate from django.dispatch import receiver from courses.models import Course +from accounts.models import CustomUser 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, unique=True) - codes = models.ManyToManyField( - 'subjects.SubjectCode') - courses = models.ManyToManyField( - 'courses.Course', through='subjects.SubjectCourse', related_name='SubjectCourse_subject') - students = models.ManyToManyField( - 'accounts.CustomUser', blank=True) - - year_levels = models.ManyToManyField( - 'year_levels.Year_Level', through='subjects.SubjectYearLevel', related_name='SubjectYearLevel_subject') - - semesters = models.ManyToManyField( - 'semesters.Semester', through='subjects.SubjectSemester', related_name='SubjectSemester_subject') def __str__(self): - code_list = ', '.join(self.codes.values_list('code', flat=True)) - return f'{self.name} ({code_list})' + return f'{self.name}' class SubjectCode(models.Model): @@ -38,46 +25,27 @@ class SubjectCode(models.Model): return self.code -class SubjectCourse(models.Model): +class SubjectInstance(models.Model): subject = models.ForeignKey( - 'subjects.Subject', on_delete=models.CASCADE, to_field='name') + 'subjects.Subject', on_delete=models.CASCADE) + students = models.ManyToManyField( + CustomUser, blank=True) + code = models.ForeignKey( + SubjectCode, on_delete=models.CASCADE) course = models.ForeignKey( - 'courses.Course', on_delete=models.CASCADE, null=True, to_field='name') - - def __str__(self): - return f'Subject={self.subject.name}, Course={self.course.name}' - - class Meta: - unique_together = [['subject', 'course']] - - -class SubjectYearLevel(models.Model): - subject = models.ForeignKey( - 'subjects.Subject', on_delete=models.CASCADE, to_field='name') + Course, on_delete=models.CASCADE) year_level = models.ForeignKey( - '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}' - - class Meta: - unique_together = [['subject', 'year_level']] - - -class SubjectSemester(models.Model): - subject = models.ForeignKey( - 'subjects.Subject', on_delete=models.CASCADE, to_field='name') + Year_Level, on_delete=models.CASCADE) semester = models.ForeignKey( - 'semesters.Semester', on_delete=models.CASCADE, to_field='name') + Semester, on_delete=models.CASCADE) def __str__(self): - return f'Subject={self.subject.name}, Semester={self.semester.name}' - - class Meta: - unique_together = [['subject', 'semester']] + return f'Subject: {self.name}({self.code}) - {self.course.shortname} - {self.year_level} - {self.semester}' # Create subjects on initial migrate + + @receiver(post_migrate) def populate_subjects(sender, **kwargs): if sender.name == 'subjects': @@ -130,37 +98,35 @@ def populate_subjects(sender, **kwargs): semester = Semester.objects.filter( name=subject_semester).first() - # If subject already exists with relevant info, skip over it - if (Subject.objects.filter(name=subject_name, year_levels=year_level, semesters=semester).exists()): - # print('Duplicate subject') - existing_subjects += 1 - continue - - # Else if subject exists without relevant info, add relevant info + # If Subject exists if (Subject.objects.filter(name=subject_name).exists()): - SUBJECT = Subject.objects.filter(name=subject_name - ).first() - SUBJECT.courses.add(course) - SUBJECT.year_levels.add(year_level) - SUBJECT.semesters.add(semester) - SUBJECT_CODE = SubjectCode.objects.get_or_create( - code=subject_code) - SUBJECT.codes.add(SUBJECT_CODE[0]) - updated_subjects += 1 + # If subject instance exists, skip over + if (SubjectInstance.objects.filter(subject__name=subject_name, year_level=year_level, semester=semester).exists()): + # print('Duplicate subject') + existing_subjects += 1 + continue + + # If no subject instance exists, create one + else: + SUBJECT = Subject.objects.filter( + name=subject_name).first() + SUBJECT_CODE, created = SubjectCode.objects.get_or_create( + code=subject_code) + SUBJECT_INSTANCE = SubjectInstance.objects.get_or_create( + subject=SUBJECT, course=course, year_level=year_level, semester=semester, code=SUBJECT_CODE) + updated_subjects += 1 # If subject does not exist at all, then create new subject else: - SUBJECT = Subject.objects.get_or_create( + SUBJECT, created = Subject.objects.get_or_create( name=subject_name, ) - SUBJECT[0].courses.set([course]) - SUBJECT[0].year_levels.set([year_level]) - SUBJECT[0].semesters.set([semester]) - SUBJECT_CODE = SubjectCode.objects.get_or_create( + SUBJECT_CODE, created = SubjectCode.objects.get_or_create( code=subject_code) - SUBJECT[0].codes.add(SUBJECT_CODE[0]) + SUBJECT_INSTANCE = SubjectInstance.objects.get_or_create( + subject=SUBJECT, course=course, year_level=year_level, semester=semester, code=SUBJECT_CODE) subject_count += 1 # Set the course, year level, and semester of the subject diff --git a/stude/subjects/serializers.py b/stude/subjects/serializers.py index f34b174..92b63da 100644 --- a/stude/subjects/serializers.py +++ b/stude/subjects/serializers.py @@ -1,21 +1,29 @@ from rest_framework import serializers -from .models import Subject, SubjectCode +from .models import Subject, SubjectInstance, SubjectCode from courses.models import Course from year_levels.models import Year_Level from semesters.models import Semester -from accounts.models import CustomUser class SubjectSerializer(serializers.ModelSerializer): - year_levels = serializers.SlugRelatedField( - queryset=Year_Level.objects.all(), many=True, slug_field='name', allow_null=True) - semesters = serializers.SlugRelatedField( - queryset=Semester.objects.all(), many=True, slug_field='name', allow_null=True) - courses = serializers.SlugRelatedField( - queryset=Course.objects.all(), many=True, slug_field='name', allow_null=True) - codes = serializers.SlugRelatedField( - queryset=SubjectCode.objects.all(), many=True, slug_field='code', allow_null=False) class Meta: model = Subject - fields = ('id', 'name', 'codes', 'courses', 'year_levels', 'semesters') + fields = '__all__' + + +class SubjectInstanceSerializer(serializers.ModelSerializer): + subject = serializers.SlugRelatedField( + queryset=SubjectCode.objects.all(), slug_field='name', allow_null=False) + code = serializers.SlugRelatedField( + queryset=SubjectCode.objects.all(), slug_field='code', allow_null=False) + year_level = serializers.SlugRelatedField( + queryset=Year_Level.objects.all(), slug_field='name', allow_null=True) + semester = serializers.SlugRelatedField( + queryset=Semester.objects.all(), slug_field='name', allow_null=True) + course = serializers.SlugRelatedField( + queryset=Course.objects.all(), slug_field='name', allow_null=True) + + class Meta: + model = SubjectInstance + fields = ('id', 'subject', 'code', 'course', 'year_level', 'semester') diff --git a/stude/subjects/views.py b/stude/subjects/views.py index f0493a2..bc7f11a 100644 --- a/stude/subjects/views.py +++ b/stude/subjects/views.py @@ -1,6 +1,6 @@ from rest_framework import generics, viewsets -from .models import Subject -from .serializers import SubjectSerializer +from .models import Subject, SubjectInstance +from .serializers import SubjectSerializer, SubjectInstanceSerializer from rest_framework.views import APIView from rest_framework.response import Response @@ -11,30 +11,27 @@ class SubjectListView(generics.ListAPIView): class SubjectByCourseView(generics.ListAPIView): - queryset = Subject.objects.all() - serializer_class = SubjectSerializer + queryset = SubjectInstance.objects.all() + serializer_class = SubjectInstanceSerializer def get(self, request, course_slug): - # Retrieve the subjects based on year level and semester slugs - subjects = Subject.objects.filter( - courses__shortname=course_slug).distinct() + # Retrieve the subjects based on course slug + subjects = SubjectInstance.objects.filter( + course__shortname=course_slug) # Serialize the subjects - serializer = SubjectSerializer(subjects, many=True) - + serializer = SubjectInstanceSerializer(subjects, many=True) return Response(serializer.data) class SubjectByCourseYearSemesterView(generics.ListAPIView): - queryset = Subject.objects.all() + queryset = SubjectInstance.objects.all() serializer_class = SubjectSerializer def get(self, request, course_slug, year_slug, semester_slug): # Retrieve the subjects based on year level and semester slugs - subjects = Subject.objects.filter( - courses__shortname=course_slug, year_levels__shortname=year_slug, semesters__shortname=semester_slug).distinct() - + subjects = SubjectInstance.objects.filter( + course__shortname=course_slug, year_level__shortname=year_slug, semester__shortname=semester_slug) # Serialize the subjects - serializer = SubjectSerializer(subjects, many=True) - + serializer = SubjectInstanceSerializer(subjects, many=True) return Response(serializer.data) diff --git a/stude/year_levels/migrations/0001_initial.py b/stude/year_levels/migrations/0001_initial.py index 2541862..5092caa 100644 --- a/stude/year_levels/migrations/0001_initial.py +++ b/stude/year_levels/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-18 07:43 +# Generated by Django 4.2.3 on 2023-07-26 03:53 from django.db import migrations, models @@ -15,8 +15,8 @@ class Migration(migrations.Migration): name='Year_Level', fields=[ ('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('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)), ], ), ] 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 deleted file mode 100644 index 2173bee..0000000 --- a/stude/year_levels/migrations/0002_alter_year_level_name_alter_year_level_shortname.py +++ /dev/null @@ -1,23 +0,0 @@ -# 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), - ), - ]