diff --git a/Pipfile b/Pipfile index d661e5c..db0b428 100644 --- a/Pipfile +++ b/Pipfile @@ -13,10 +13,9 @@ whitenoise = "*" djangochannelsrestframework = "*" daphne = "*" psycopg2 = "*" -gdal = "*" django-leaflet = "*" django-extra-fields = "*" -drf-spectacular = "*" +drf-spectacular = {extras = ["sidecar"], version = "*"} [dev-packages] diff --git a/Pipfile.lock b/Pipfile.lock index 3e1af89..ff7d582 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "2af7c1a36777c63d117eec851085d362eaaa1d3205b7780938bfb5e2e4133b69" + "sha256": "a4f6715106c65a972a21b76a8e9f6ca4b79337de9f54f8012b47b146a41c2bfc" }, "pipfile-spec": 6, "requires": { @@ -327,6 +327,9 @@ "version": "==2.2.0" }, "drf-spectacular": { + "extras": [ + "sidecar" + ], "hashes": [ "sha256:8f5a8f87353d1bb8dcb3f3909b7109b2dcbe1d91f3e069409cf322963e140bd6", "sha256:afeccc6533dcdb4e78afbfcc49f3c5e9c369aeb62f965e4d1a43b165449c147a" @@ -334,12 +337,12 @@ "index": "pypi", "version": "==0.26.4" }, - "gdal": { + "drf-spectacular-sidecar": { "hashes": [ - "sha256:f78861fb5115d5c2f8cf3c52a492ff548da9e1256dc84088947379f90e77e5b6" + "sha256:4466e396a875182ac568872cd7a6658fefc386a764272adf088ce7a8d80c795a", + "sha256:fae346a00636a57aa164d2778e7162cfaff1f59af8133c2b6a8403c8211a167b" ], - "path": "./packages/GDAL-3.4.3-cp311-cp311-win_amd64.whl", - "version": "==3.4.3" + "version": "==2023.7.1" }, "hyperlink": { "hashes": [ @@ -353,7 +356,6 @@ "sha256:814f528e8dead7d329833b91c5faa87d60bf71824cd12a7530b5526063d02cb4", "sha256:90b77e79eaa3eba6de819a0c442c0b4ceefc341a7a2ab77d7562bf49f425c5c2" ], - "markers": "python_version >= '3.5'", "version": "==3.4" }, "incremental": { @@ -729,7 +731,7 @@ "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926", "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254" ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", "version": "==1.16.0" }, "social-auth-app-django": { diff --git a/packages/GDAL-3.4.3-cp311-cp311-win_amd64.whl b/packages/GDAL-3.4.3-cp311-cp311-win_amd64.whl new file mode 100644 index 0000000..573d1c0 Binary files /dev/null and b/packages/GDAL-3.4.3-cp311-cp311-win_amd64.whl differ diff --git a/stude/accounts/admin.py b/stude/accounts/admin.py index 37df597..3fe2828 100644 --- a/stude/accounts/admin.py +++ b/stude/accounts/admin.py @@ -30,7 +30,7 @@ class CustomUserAdmin(UserAdmin): fieldsets = UserAdmin.fieldsets + ( (None, {'fields': ('student_id_number', - 'year_level', 'semester', 'course', 'subjects', 'avatar', 'is_student', 'is_banned')}), + 'year_level', 'semester', 'course', 'subjects', 'avatar', 'is_student', 'irregular')}), ) diff --git a/stude/accounts/migrations/0001_initial.py b/stude/accounts/migrations/0001_initial.py index 4836bd0..f5780ff 100644 --- a/stude/accounts/migrations/0001_initial.py +++ b/stude/accounts/migrations/0001_initial.py @@ -1,4 +1,4 @@ -# Generated by Django 4.2.3 on 2023-07-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 import accounts.models import django.contrib.auth.models @@ -13,9 +13,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ + ('semesters', '0001_initial'), ('courses', '0001_initial'), ('auth', '0012_alter_user_first_name_max_length'), - ('semesters', '0001_initial'), ] operations = [ @@ -35,7 +35,7 @@ class Migration(migrations.Migration): ('is_active', models.BooleanField(default=False)), ('is_student', models.BooleanField(default=True)), ('is_studying', models.BooleanField(default=False)), - ('is_banned', models.BooleanField(default=False)), + ('irregular', 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')), diff --git a/stude/accounts/migrations/0002_initial.py b/stude/accounts/migrations/0002_initial.py index 6f57ff3..2983227 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 from django.db import migrations, models import django.db.models.deletion @@ -9,9 +9,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('year_levels', '0001_initial'), ('subjects', '0001_initial'), ('accounts', '0001_initial'), + ('year_levels', '0001_initial'), ('auth', '0012_alter_user_first_name_max_length'), ] @@ -19,7 +19,7 @@ class Migration(migrations.Migration): migrations.AddField( model_name='customuser', name='subjects', - field=models.ManyToManyField(to='subjects.subjectinstance'), + field=models.ManyToManyField(to='subjects.subject'), ), migrations.AddField( model_name='customuser', diff --git a/stude/accounts/models.py b/stude/accounts/models.py index 5edfbda..228da22 100644 --- a/stude/accounts/models.py +++ b/stude/accounts/models.py @@ -34,7 +34,7 @@ class CustomUser(AbstractUser): is_active = models.BooleanField(default=False) is_student = models.BooleanField(default=True) is_studying = models.BooleanField(default=False) - is_banned = models.BooleanField(default=False) + irregular = models.BooleanField(default=False) student_id_number = models.CharField( max_length=16, validators=[validate_student_id], null=False) avatar = models.ImageField(upload_to=_get_upload_to, null=True) @@ -53,7 +53,7 @@ class CustomUser(AbstractUser): on_delete=models.SET_NULL, null=True ) - subjects = models.ManyToManyField('subjects.SubjectInstance') + subjects = models.ManyToManyField('subjects.Subject') @property def full_name(self): diff --git a/stude/accounts/serializers.py b/stude/accounts/serializers.py index a8b9dad..2788f98 100644 --- a/stude/accounts/serializers.py +++ b/stude/accounts/serializers.py @@ -13,11 +13,25 @@ from year_levels.models import Year_Level from semesters.models import Semester from subjects.models import Subject from django.contrib.gis.geos import Point +from django.utils.encoding import smart_str + +# There can be multiple subject instances with the same name, only differing in course, year level, and semester. We filter them here + + +class SubjectSlugRelatedField(serializers.SlugRelatedField): + def to_internal_value(self, data): + user_course = self.context['request'].user.course + try: + subject = Subject.objects.get(name=data, course=user_course) + return subject + except Subject.DoesNotExist: + self.fail('does_not_exist', slug_name=self.slug_field, + value=smart_str(data)) + except (TypeError, ValueError): + self.fail('invalid') class CustomUserSerializer(BaseUserSerializer): - # user_status = StudentStatusSerializer( - # source='studentstatus', read_only=True) course_shortname = serializers.SerializerMethodField() yearlevel_shortname = serializers.SerializerMethodField() semester_shortname = serializers.SerializerMethodField() @@ -27,14 +41,15 @@ class CustomUserSerializer(BaseUserSerializer): many=False, slug_field='name', queryset=Year_Level.objects.all(), required=False, allow_null=True) semester = serializers.SlugRelatedField( many=False, slug_field='name', queryset=Semester.objects.all(), required=False, allow_null=True) - subjects = serializers.SlugRelatedField( - many=True, slug_field='name', queryset=Subject.objects.all(), required=False, allow_null=True) + # Use custom slug field for filtering + subjects = SubjectSlugRelatedField( + many=True, slug_field='name', queryset=Subject.objects.all(), required=False) class Meta(BaseUserSerializer.Meta): model = CustomUser fields = ('username', 'email', - 'student_id_number', 'year_level', 'yearlevel_shortname', 'semester', 'semester_shortname', 'course', 'course_shortname', 'subjects', 'avatar', 'first_name', 'last_name', 'is_banned') - read_only_fields = ('is_banned', 'user_status', 'yearlevel_shortname', + 'student_id_number', 'year_level', 'yearlevel_shortname', 'semester', 'semester_shortname', 'course', 'course_shortname', 'subjects', 'avatar', 'first_name', 'last_name', 'irregular') + read_only_fields = ('user_status', 'yearlevel_shortname', 'semester_shortname', 'course_shortname') def get_course_shortname(self, instance): @@ -51,9 +66,9 @@ class CustomUserSerializer(BaseUserSerializer): print(validated_data) # If course, year_level, or semester is changed if any(field in validated_data for field in ['course', 'year_level', 'semester']): - if (instance.course != validated_data['course'] or - instance.year_level != validated_data['year_level'] or - instance.semester != validated_data['semester']): + if (instance.course not in validated_data['course'] or + instance.year_level not in validated_data['year_level'] or + instance.semester not in validated_data['semester']): # Clear all subjects instance.subjects.clear() @@ -61,17 +76,16 @@ class CustomUserSerializer(BaseUserSerializer): instance = super().update(instance, validated_data) # Then add new subjects matching the new criteria self.add_subjects(instance) - - # Else update as usual else: - instance = super().update(instance, validated_data) + # Else update as usual + super().update(instance, validated_data) return instance def add_subjects(self, instance): # Get the matching subjects based on the user's course, year level, and semester matching_subjects = Subject.objects.filter( - courses=instance.course, year_levels=instance.year_level, semesters=instance.semester) + course=instance.course, year_level=instance.year_level, semester=instance.semester) # Add the matching subjects to the user's subjects list instance.subjects.add(*matching_subjects) diff --git a/stude/config/settings.py b/stude/config/settings.py index f77c11e..ebb3a62 100644 --- a/stude/config/settings.py +++ b/stude/config/settings.py @@ -40,6 +40,9 @@ SPECTACULAR_SETTINGS = { 'DESCRIPTION': 'A Capstone project', 'VERSION': '1.0.0', 'SERVE_INCLUDE_SCHEMA': False, + 'SWAGGER_UI_DIST': 'SIDECAR', + 'SWAGGER_UI_FAVICON_HREF': 'SIDECAR', + 'REDOC_DIST': 'SIDECAR', # OTHER SETTINGS } @@ -87,6 +90,7 @@ INSTALLED_APPS = [ 'django.contrib.messages', 'django.contrib.staticfiles', 'drf_spectacular', + 'drf_spectacular_sidecar', 'django.contrib.gis', 'rest_framework', 'rest_framework_simplejwt', diff --git a/stude/courses/migrations/0001_initial.py b/stude/courses/migrations/0001_initial.py index 95ddace..23dbfdc 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 from django.db import migrations, models diff --git a/stude/landmarks/migrations/0001_initial.py b/stude/landmarks/migrations/0001_initial.py index ec11adf..d4b6d96 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 import django.contrib.gis.db.models.fields from django.db import migrations, models diff --git a/stude/schema.yml b/stude/schema.yml index 1fb3e11..7fc405f 100644 --- a/stude/schema.yml +++ b/stude/schema.yml @@ -744,6 +744,28 @@ paths: - api security: - jwtAuth: [] + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Subject' + description: '' + /api/v1/subjects/{course_slug}: + get: + operationId: api_v1_subjects_list_2 + parameters: + - in: path + name: course_slug + schema: + type: string + required: true + tags: + - api + security: + - jwtAuth: [] - {} responses: '200': @@ -756,7 +778,7 @@ paths: description: '' /api/v1/subjects/{course_slug}/{year_slug}/{semester_slug}: get: - operationId: api_v1_subjects_list_2 + operationId: api_v1_subjects_list_3 parameters: - in: path name: course_slug @@ -787,6 +809,23 @@ paths: items: $ref: '#/components/schemas/Subject' description: '' + /api/v1/subjects/all: + get: + operationId: api_v1_subjects_all_list + tags: + - api + security: + - jwtAuth: [] + - {} + responses: + '200': + content: + application/json: + schema: + type: array + items: + $ref: '#/components/schemas/Subject' + description: '' /api/v1/year_levels/: get: operationId: api_v1_year_levels_list @@ -828,16 +867,10 @@ components: shortname: type: string maxLength: 16 - subjects: - type: array - items: - type: string - readOnly: true required: - id - name - shortname - - subjects CustomUser: type: object properties: @@ -888,13 +921,13 @@ components: last_name: type: string maxLength: 100 - is_banned: + irregular: type: boolean readOnly: true required: - course_shortname - first_name - - is_banned + - irregular - last_name - semester_shortname - student_id_number @@ -1001,7 +1034,7 @@ components: last_name: type: string maxLength: 100 - is_banned: + irregular: type: boolean readOnly: true PatchedStudentStatus: @@ -1146,35 +1179,27 @@ components: id: type: integer readOnly: true - name: + subject: type: string - maxLength: 64 - codes: - type: array - items: - type: string - courses: - type: array - items: - type: string - nullable: true - year_levels: - type: array - items: - type: string - nullable: true - semesters: - type: array - items: - type: string - nullable: true + code: + type: string + maxLength: 16 + course: + type: string + nullable: true + year_level: + type: string + nullable: true + semester: + type: string + nullable: true required: - - codes - - courses + - code + - course - id - - name - - semesters - - year_levels + - semester + - subject + - year_level TokenObtainPair: type: object properties: diff --git a/stude/semesters/migrations/0001_initial.py b/stude/semesters/migrations/0001_initial.py index 4d2fd50..1de922f 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 from django.db import migrations, models diff --git a/stude/student_status/migrations/0001_initial.py b/stude/student_status/migrations/0001_initial.py index 586e080..8daa441 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 from django.conf import settings import django.contrib.gis.db.models.fields diff --git a/stude/student_status/migrations/0002_initial.py b/stude/student_status/migrations/0002_initial.py index 954ef5b..b55be6c 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 from django.db import migrations, models import django.db.models.deletion @@ -9,9 +9,9 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('student_status', '0001_initial'), ('study_groups', '0001_initial'), ('subjects', '0001_initial'), + ('student_status', '0001_initial'), ] operations = [ diff --git a/stude/study_groups/migrations/0001_initial.py b/stude/study_groups/migrations/0001_initial.py index 4cde52a..21dc0be 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 import django.contrib.gis.db.models.fields from django.db import migrations, models @@ -10,8 +10,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('student_status', '0001_initial'), ('subjects', '0001_initial'), + ('student_status', '0001_initial'), ] operations = [ diff --git a/stude/study_groups/views.py b/stude/study_groups/views.py index 4d7a65b..aa70158 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 SubjectInstance +from subjects.models import Subject # Create your views here. @@ -26,7 +26,7 @@ class StudyGroupListView(generics.ListAPIView): print(user_course) # Get subject names related to the user's course - subject_names = SubjectInstance.objects.filter( + subject_names = Subject.objects.filter( course=user_course ).values_list('subject', flat=True) diff --git a/stude/studygroup_messages/migrations/0001_initial.py b/stude/studygroup_messages/migrations/0001_initial.py index d2b9301..52431c5 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 from django.conf import settings from django.db import migrations, models @@ -10,8 +10,8 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('study_groups', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('study_groups', '0001_initial'), ] operations = [ diff --git a/stude/subjects/admin.py b/stude/subjects/admin.py index de056f7..6a58e86 100644 --- a/stude/subjects/admin.py +++ b/stude/subjects/admin.py @@ -1,6 +1,4 @@ from django.contrib import admin -from .models import Subject, SubjectCode, SubjectInstance +from .models import Subject 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 c654efa..9c3b8b6 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 from django.conf import settings from django.db import migrations, models @@ -10,10 +10,10 @@ class Migration(migrations.Migration): initial = True dependencies = [ - ('courses', '0001_initial'), - ('year_levels', '0001_initial'), migrations.swappable_dependency(settings.AUTH_USER_MODEL), + ('courses', '0001_initial'), ('semesters', '0001_initial'), + ('year_levels', '0001_initial'), ] operations = [ @@ -21,25 +21,11 @@ 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, unique=True)), - ], - ), - migrations.CreateModel( - name='SubjectCode', - 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, 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')), ], ), diff --git a/stude/subjects/migrations/0002_alter_subject_code.py b/stude/subjects/migrations/0002_alter_subject_code.py new file mode 100644 index 0000000..71cc3f8 --- /dev/null +++ b/stude/subjects/migrations/0002_alter_subject_code.py @@ -0,0 +1,18 @@ +# Generated by Django 4.2.3 on 2023-07-26 12:08 + +from django.db import migrations, models + + +class Migration(migrations.Migration): + + dependencies = [ + ('subjects', '0001_initial'), + ] + + operations = [ + migrations.AlterField( + model_name='subject', + name='code', + field=models.CharField(max_length=16), + ), + ] diff --git a/stude/subjects/models.py b/stude/subjects/models.py index e44217a..a1e4489 100644 --- a/stude/subjects/models.py +++ b/stude/subjects/models.py @@ -12,26 +12,10 @@ from semesters.models import Semester class Subject(models.Model): - name = models.CharField(max_length=64, unique=True) - - def __str__(self): - return f'{self.name}' - - -class SubjectCode(models.Model): - code = models.CharField(max_length=16, unique=True) - - def __str__(self): - return self.code - - -class SubjectInstance(models.Model): - subject = models.ForeignKey( - 'subjects.Subject', on_delete=models.CASCADE) + name = models.CharField(max_length=64) students = models.ManyToManyField( CustomUser, blank=True) - code = models.ForeignKey( - SubjectCode, on_delete=models.CASCADE) + code = models.CharField(max_length=16) course = models.ForeignKey( Course, on_delete=models.CASCADE) year_level = models.ForeignKey( @@ -39,10 +23,11 @@ class SubjectInstance(models.Model): semester = models.ForeignKey( Semester, on_delete=models.CASCADE) + class Meta: + unique_together = ['name', 'course', 'year_level', 'semester'] + def __str__(self): return f'Subject: {self.name}({self.code}) - {self.course.shortname} - {self.year_level} - {self.semester}' - - # Create subjects on initial migrate @@ -62,7 +47,6 @@ def populate_subjects(sender, **kwargs): reader = csv.reader(csvfile) next(reader) # Skip the header row subject_count = 0 - updated_subjects = 0 ignored_subjects = 0 existing_subjects = 0 for row in reader: @@ -98,41 +82,22 @@ def populate_subjects(sender, **kwargs): semester = Semester.objects.filter( name=subject_semester).first() - # If Subject exists - if (Subject.objects.filter(name=subject_name).exists()): - - # 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 exists, skip over + if (Subject.objects.filter(name=subject_name, course=course, year_level=year_level, semester=semester, code=subject_code).exists()): + # print('Duplicate subject') + existing_subjects += 1 + continue # If subject does not exist at all, then create new subject else: SUBJECT, created = Subject.objects.get_or_create( - name=subject_name, - ) - 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) + name=subject_name, course=course, year_level=year_level, semester=semester, code=subject_code) subject_count += 1 # Set the course, year level, and semester of the subject print('Skipped', existing_subjects, 'already existing subjects') print('Added', subject_count, 'subjects') - print('Updated', updated_subjects, 'subjects') print('Ignored', ignored_subjects, 'subjects', '\n') diff --git a/stude/subjects/serializers.py b/stude/subjects/serializers.py index 92b63da..6f9c30c 100644 --- a/stude/subjects/serializers.py +++ b/stude/subjects/serializers.py @@ -1,22 +1,11 @@ from rest_framework import serializers -from .models import Subject, SubjectInstance, SubjectCode +from .models import Subject from courses.models import Course from year_levels.models import Year_Level from semesters.models import Semester class SubjectSerializer(serializers.ModelSerializer): - - class Meta: - model = Subject - 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( @@ -25,5 +14,5 @@ class SubjectInstanceSerializer(serializers.ModelSerializer): queryset=Course.objects.all(), slug_field='name', allow_null=True) class Meta: - model = SubjectInstance - fields = ('id', 'subject', 'code', 'course', 'year_level', 'semester') + model = Subject + fields = ('id', 'name', 'code', 'course', 'year_level', 'semester') diff --git a/stude/subjects/urls.py b/stude/subjects/urls.py index b1c131f..8443131 100644 --- a/stude/subjects/urls.py +++ b/stude/subjects/urls.py @@ -1,8 +1,8 @@ from django.urls import include, path -from .views import SubjectByCourseView, SubjectByCourseYearSemesterView, SubjectListView -from rest_framework import routers +from .views import SubjectByCourseView, SubjectByCourseYearSemesterView, SubjectListView, SubjectListAllView urlpatterns = [ path('', SubjectListView.as_view()), + path('all', SubjectListAllView.as_view()), path('', SubjectByCourseView.as_view()), path('//', diff --git a/stude/subjects/views.py b/stude/subjects/views.py index bc7f11a..865a785 100644 --- a/stude/subjects/views.py +++ b/stude/subjects/views.py @@ -1,37 +1,63 @@ from rest_framework import generics, viewsets -from .models import Subject, SubjectInstance -from .serializers import SubjectSerializer, SubjectInstanceSerializer +from .models import Subject +from .serializers import SubjectSerializer from rest_framework.views import APIView from rest_framework.response import Response +from rest_framework.permissions import IsAuthenticated -class SubjectListView(generics.ListAPIView): +class SubjectListAllView(generics.ListAPIView): serializer_class = SubjectSerializer queryset = Subject.objects.all() +class SubjectListView(generics.ListAPIView): + permission_classes = [IsAuthenticated] + queryset = Subject.objects.all() + serializer_class = SubjectSerializer + + def get(self, request): + user = self.request.user + user_course = user.course + # If user is irregular, show all subjects in his/her course to choose from + if (user.irregular): + subjects = Subject.objects.filter( + course__name=user_course) + + # Else, return subjects that match the user's student info (Year Level, Semster, Course) + else: + user_yearlevel = user.year_level + user_semester = user.semester + subjects = Subject.objects.filter( + course__name=user.course, year_level__name=user_yearlevel, semester__name=user_semester) + + # Serialize the subjects + serializer = SubjectSerializer(subjects, many=True) + return Response(serializer.data) + + class SubjectByCourseView(generics.ListAPIView): - queryset = SubjectInstance.objects.all() - serializer_class = SubjectInstanceSerializer + queryset = Subject.objects.all() + serializer_class = SubjectSerializer def get(self, request, course_slug): # Retrieve the subjects based on course slug - subjects = SubjectInstance.objects.filter( + subjects = Subject.objects.filter( course__shortname=course_slug) # Serialize the subjects - serializer = SubjectInstanceSerializer(subjects, many=True) + serializer = SubjectSerializer(subjects, many=True) return Response(serializer.data) class SubjectByCourseYearSemesterView(generics.ListAPIView): - queryset = SubjectInstance.objects.all() + queryset = Subject.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 = SubjectInstance.objects.filter( + subjects = Subject.objects.filter( course__shortname=course_slug, year_level__shortname=year_slug, semester__shortname=semester_slug) # Serialize the subjects - serializer = SubjectInstanceSerializer(subjects, many=True) + serializer = SubjectSerializer(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 5092caa..6c0ec08 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-26 03:53 +# Generated by Django 4.2.3 on 2023-07-26 12:06 from django.db import migrations, models