2023-06-26 19:45:58 +08:00
from djoser . serializers import UserCreateSerializer as BaseUserRegistrationSerializer
from djoser . serializers import UserSerializer as BaseUserSerializer
2023-07-03 21:22:06 +08:00
from django . core import exceptions as django_exceptions
from rest_framework import exceptions as drf_exceptions
2023-06-28 17:12:14 +08:00
from rest_framework import serializers
2023-06-26 19:45:58 +08:00
from accounts . models import CustomUser
2023-06-26 22:06:05 +08:00
from student_status . serializers import StudentStatusSerializer
2023-06-26 23:50:55 +08:00
from student_status . models import StudentStatus
2023-07-03 21:22:06 +08:00
from rest_framework . settings import api_settings
from django . contrib . auth . password_validation import validate_password
2023-07-06 21:47:28 +08:00
from courses . models import Course
from year_levels . models import Year_Level
from semesters . models import Semester
2023-07-18 16:01:19 +08:00
from subjects . models import Subject
2023-07-09 19:00:47 +08:00
from django . contrib . gis . geos import Point
2023-07-26 23:32:03 +08:00
from django . utils . encoding import smart_str
2023-07-27 00:43:31 +08:00
from drf_spectacular . utils import extend_schema_field
from drf_spectacular . types import OpenApiTypes
2023-07-27 16:00:24 +08:00
from drf_extra_fields . fields import Base64ImageField
2023-07-26 23:32:03 +08:00
# 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 ' )
2023-06-26 19:45:58 +08:00
class CustomUserSerializer ( BaseUserSerializer ) :
2023-07-18 00:35:41 +08:00
course_shortname = serializers . SerializerMethodField ( )
yearlevel_shortname = serializers . SerializerMethodField ( )
semester_shortname = serializers . SerializerMethodField ( )
2023-07-06 21:47:28 +08:00
course = serializers . SlugRelatedField (
many = False , slug_field = ' name ' , queryset = Course . objects . all ( ) , required = False , allow_null = True )
year_level = serializers . SlugRelatedField (
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 )
2023-07-26 23:32:03 +08:00
# Use custom slug field for filtering
subjects = SubjectSlugRelatedField (
many = True , slug_field = ' name ' , queryset = Subject . objects . all ( ) , required = False )
2023-07-27 16:00:24 +08:00
avatar = Base64ImageField ( )
2023-06-26 22:06:05 +08:00
2023-06-26 19:45:58 +08:00
class Meta ( BaseUserSerializer . Meta ) :
model = CustomUser
2023-07-04 20:34:12 +08:00
fields = ( ' username ' , ' email ' ,
2023-07-26 23:32:03 +08:00
' 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 ' ,
2023-07-18 00:36:13 +08:00
' semester_shortname ' , ' course_shortname ' )
2023-06-26 19:45:58 +08:00
2023-07-27 00:43:31 +08:00
@extend_schema_field ( OpenApiTypes . STR )
2023-07-18 00:35:41 +08:00
def get_course_shortname ( self , instance ) :
return instance . course . shortname if instance . course else None
2023-07-27 00:43:31 +08:00
@extend_schema_field ( OpenApiTypes . STR )
2023-07-18 00:35:41 +08:00
def get_yearlevel_shortname ( self , instance ) :
return instance . year_level . shortname if instance . year_level else None
2023-07-27 00:43:31 +08:00
@extend_schema_field ( OpenApiTypes . STR )
2023-07-18 00:35:41 +08:00
def get_semester_shortname ( self , instance ) :
return instance . semester . shortname if instance . semester else None
2023-07-18 17:56:23 +08:00
def update ( self , instance , validated_data ) :
# First, we'll remove all the existing subjects from the user
2023-07-18 22:13:31 +08:00
print ( validated_data )
# If course, year_level, or semester is changed
2023-07-18 22:15:42 +08:00
if any ( field in validated_data for field in [ ' course ' , ' year_level ' , ' semester ' ] ) :
2023-07-27 00:10:53 +08:00
if (
instance . course is not validated_data [ ' course ' ] or
instance . year_level is not validated_data [ ' year_level ' ] or
instance . semester is not validated_data [ ' semester ' ] or
instance . irregular is not validated_data [ ' irregular ' ] ) :
2023-07-18 17:56:23 +08:00
2023-07-18 22:13:31 +08:00
# Clear all subjects
instance . subjects . clear ( )
# Update the user instance with the validated data
instance = super ( ) . update ( instance , validated_data )
# Then add new subjects matching the new criteria
self . add_subjects ( instance )
2023-07-27 00:10:53 +08:00
# This is what I want you to do. This comment below! Ignore any other comments
# Add another condition here to check if the user recently changed his/her irregular field from true to false. And if it has changed to false from being true, run the same if statement above
2023-07-18 22:13:31 +08:00
else :
2023-07-26 23:32:03 +08:00
# Else update as usual
super ( ) . update ( instance , validated_data )
2023-07-18 17:56:23 +08:00
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 (
2023-07-26 23:32:03 +08:00
course = instance . course , year_level = instance . year_level , semester = instance . semester )
2023-07-18 17:56:23 +08:00
# Add the matching subjects to the user's subjects list
instance . subjects . add ( * matching_subjects )
2023-07-03 21:22:06 +08:00
# The model from your custom user
2023-06-26 19:45:58 +08:00
2023-07-03 21:22:06 +08:00
class UserRegistrationSerializer ( serializers . ModelSerializer ) :
email = serializers . EmailField ( required = True )
student_id_number = serializers . CharField ( required = True )
2023-07-09 19:00:47 +08:00
password = serializers . CharField (
write_only = True , style = { ' input_type ' : ' password ' , ' placeholder ' : ' Password ' } )
2023-07-19 02:38:35 +08:00
subjects = serializers . SlugRelatedField (
many = True , slug_field = ' name ' , queryset = Subject . objects . all ( ) , required = False , allow_null = True )
2023-07-03 21:22:06 +08:00
class Meta :
model = CustomUser # Use your custom user model here
fields = ( ' username ' , ' email ' , ' password ' , ' student_id_number ' ,
' year_level ' , ' semester ' , ' course ' , ' subjects ' , ' avatar ' ,
' first_name ' , ' last_name ' )
def validate ( self , attrs ) :
user = self . Meta . model ( * * attrs )
password = attrs . get ( " password " )
try :
validate_password ( password , user )
except django_exceptions . ValidationError as e :
serializer_error = serializers . as_serializer_error ( e )
raise serializers . ValidationError (
{ " password " : serializer_error [ api_settings . NON_FIELD_ERRORS_KEY ] }
)
return super ( ) . validate ( attrs )
2023-06-26 23:50:55 +08:00
def create ( self , validated_data ) :
user = self . Meta . model ( * * validated_data )
2023-07-03 21:22:06 +08:00
user . set_password ( validated_data [ ' password ' ] )
user . save ( )
2023-06-26 23:50:55 +08:00
2023-06-26 23:56:51 +08:00
StudentStatus . objects . create (
2023-06-26 23:50:55 +08:00
user = user ,
active = False ,
2023-07-09 19:00:47 +08:00
location = Point ( 0 , 0 ) ,
2023-06-26 23:50:55 +08:00
subject = None
)
return user