11from django .db import models
22from django .contrib .auth .models import User
3- # from backend. apps.uploads.models import UploadRecord - This will be revised and corrected
3+ from apps .uploads .models import UploadRecord
44from django .core .exceptions import ValidationError
55from django .core .validators import MinValueValidator
66
@@ -19,8 +19,8 @@ class Assignment(models.Model): # Assignments: Represents assignments given to
1919 description = models .TextField (blank = True )
2020 assignment_type = models .CharField (max_length = 2 , choices = ASSIGNMENT_TYPES )
2121
22- # Upload_record (ForeignKey to UploadRecord) - Currently not referenced correctly but will be when branch is updated
23- # upload_record = models.ForeignKey(UploadRecord, on_delete=models.SET_NULL, null=True, blank=True)
22+ # Upload_record (ForeignKey to UploadRecord)
23+ upload_record = models .ForeignKey (UploadRecord , on_delete = models .SET_NULL , null = True , blank = True )
2424
2525 # Student (ForeignKey to User as there's no model exclusively for student)
2626 student = models .ForeignKey (User , on_delete = models .CASCADE , related_name = "assignments" , null = True , blank = True )
@@ -31,6 +31,22 @@ class Assignment(models.Model): # Assignments: Represents assignments given to
3131 def __str__ (self ):
3232 return self .title
3333
34+ # Helper methods
35+ @classmethod
36+ def get_assignment (cls , assignment_id ):
37+ try :
38+ return cls .objects .get (pk = assignment_id )
39+ except cls .DoesNotExist :
40+ return None
41+
42+ def update_assignment (self , data ):
43+ for field , value in data .items ():
44+ setattr (self , field , value )
45+ self .save ()
46+ return self
47+
48+ def delete_assignment (self ):
49+ self .delete ()
3450
3551class Quiz (models .Model ): # Quizzes: Represents quizzes linked to assignments.
3652 class Meta :
@@ -46,6 +62,14 @@ class Meta:
4662 def __str__ (self ):
4763 return f"Quiz for { self .assignment .title } "
4864
65+ # Helper Method(s)
66+ @classmethod
67+ def get_quiz (cls , quiz_id ):
68+ try :
69+ return cls .objects .get (pk = quiz_id )
70+ except cls .DoesNotExist :
71+ return None
72+
4973
5074class Question (models .Model ): # Questions: Represents individual questions within a quiz.
5175 QUESTION_TYPES = [
@@ -57,13 +81,29 @@ class Question(models.Model): # Questions: Represents individual questions with
5781 question_type = models .CharField (max_length = 2 , choices = QUESTION_TYPES )
5882 order_of_question = models .PositiveIntegerField ()
5983 question_text = models .TextField ()
60- # New field to store points/score for the question
6184 points = models .PositiveIntegerField (default = 1 , help_text = "Points assigned to this question" )
6285
6386 def __str__ (self ):
6487 quiz_title = self .quiz .assignment .title if self .quiz and self .quiz .assignment else "Unknown Quiz"
6588 return f"Question { self .order_of_question } - { quiz_title } "
6689
90+ # Helper Methods
91+ @classmethod
92+ def get_question (cls , question_id ):
93+ try :
94+ return cls .objects .get (pk = question_id )
95+ except cls .DoesNotExist :
96+ return None
97+
98+ def update_question (self , data ):
99+ for field , value in data .items ():
100+ setattr (self , field , value )
101+ self .save ()
102+ return self
103+
104+ def delete_question (self ):
105+ self .delete ()
106+
67107
68108class Choice (models .Model ): # Choices: Store the possible answer choices for multiple choice questions.
69109 # Fields
@@ -74,15 +114,48 @@ class Choice(models.Model): # Choices: Store the possible answer choices for mu
74114 def __str__ (self ):
75115 return f"Choice: { self .choice_text } ({ 'Correct' if self .is_correct else 'Incorrect' } )"
76116
117+ # Helper Methods
118+ @classmethod
119+ def get_choices (cls , question ):
120+ return cls .objects .filter (question = question )
121+
122+ @classmethod
123+ def delete_choices (cls , question ):
124+ cls .objects .filter (question = question ).delete ()
125+ # self.delete()
126+
127+ @classmethod
128+ def bulk_create_choices (cls , choices_data , question ):
129+ # double check **choice_data - saw this online ;)
130+ choices = [cls (question = question , ** choice_data ) for choice_data in choices_data ]
131+ return cls .objects .bulk_create (choices )
132+
133+ @classmethod
134+ def bulk_update_choices (cls , choices_data , question ):
135+ existing_choices = cls .objects .filter (question = question )
136+
137+ choices_to_update = []
138+ for choice_data in choices_data :
139+ choice_id = choice_data .get ("id" )
140+ choice_obj = existing_choices .filter (id = choice_id ).first ()
141+
142+ if choice_obj :
143+ for field , value in choice_data .items ():
144+ setattr (choice_obj , field , value )
145+ choices_to_update .append (choice_obj )
146+
147+ if choices_to_update :
148+ cls .objects .bulk_update (choices_to_update , ["choice_text" , "is_correct" ])
149+
77150
78151class Solution (models .Model ): # Solutions: Represents correct answers to questions.
79152 # Fields
80153 question = models .ForeignKey (Question , on_delete = models .CASCADE )
81154 choices = models .ManyToManyField (Choice , blank = True ) # for multiple choice questions
82155 short_answer_text = models .TextField (blank = True , null = True ) # for short answer questions
83-
84- # New validation that ensures MC questions have at least one correct answer
156+
85157 def clean (self ):
158+ # validation that ensures MC questions have at least one correct answer
86159 if self .question .question_type == 'MC' and not self .choices .filter (is_correct = True ).exists ():
87160 raise ValidationError ("A multiple-choice question must have at least one correct answer." )
88161
0 commit comments