Commit 8806ae51b7721986965cb79fd13f2b02569f5ff6

Authored by Rohan Rangray
1 parent ff1c4d11d6
Exists in master

Fixed stupid bug :(

Showing 1 changed file with 1 additions and 1 deletions Inline Diff

flashcards/serializers.py View file @ 8806ae5
from json import loads 1 1 from json import loads
from collections import Iterable 2 2 from collections import Iterable
3 3
from django.utils.datetime_safe import datetime 4 4 from django.utils.datetime_safe import datetime
from django.utils.timezone import now 5 5 from django.utils.timezone import now
from flashcards.models import Section, LecturePeriod, User, Flashcard, UserFlashcardQuiz 6 6 from flashcards.models import Section, LecturePeriod, User, Flashcard, UserFlashcardQuiz
from flashcards.validators import FlashcardMask, OverlapIntervalException 7 7 from flashcards.validators import FlashcardMask, OverlapIntervalException
from rest_framework import serializers 8 8 from rest_framework import serializers
from rest_framework.fields import EmailField, BooleanField, CharField, IntegerField, DateTimeField, empty, \ 9 9 from rest_framework.fields import EmailField, BooleanField, CharField, IntegerField, DateTimeField, empty, \
SerializerMethodField, FloatField 10 10 SerializerMethodField, FloatField
from rest_framework.serializers import ModelSerializer, Serializer, PrimaryKeyRelatedField, ListField 11 11 from rest_framework.serializers import ModelSerializer, Serializer, PrimaryKeyRelatedField, ListField
from rest_framework.validators import UniqueValidator 12 12 from rest_framework.validators import UniqueValidator
from flashy.settings import QUARTER_END, QUARTER_START 13 13 from flashy.settings import QUARTER_END, QUARTER_START
14 14
15 15
class EmailSerializer(Serializer): 16 16 class EmailSerializer(Serializer):
email = EmailField(required=True) 17 17 email = EmailField(required=True)
18 18
19 19
class EmailPasswordSerializer(EmailSerializer): 20 20 class EmailPasswordSerializer(EmailSerializer):
password = CharField(required=True) 21 21 password = CharField(required=True)
22 22
23 23
class RegistrationSerializer(EmailPasswordSerializer): 24 24 class RegistrationSerializer(EmailPasswordSerializer):
email = EmailField(required=True, validators=[UniqueValidator(queryset=User.objects.all())]) 25 25 email = EmailField(required=True, validators=[UniqueValidator(queryset=User.objects.all())])
26 26
27 27
class PasswordResetRequestSerializer(EmailSerializer): 28 28 class PasswordResetRequestSerializer(EmailSerializer):
def validate_email(self, value): 29 29 def validate_email(self, value):
try: 30 30 try:
User.objects.get(email=value) 31 31 User.objects.get(email=value)
return value 32 32 return value
except User.DoesNotExist: 33 33 except User.DoesNotExist:
raise serializers.ValidationError('No user exists with that email') 34 34 raise serializers.ValidationError('No user exists with that email')
35 35
36 36
class PasswordResetSerializer(Serializer): 37 37 class PasswordResetSerializer(Serializer):
new_password = CharField(required=True, allow_blank=False) 38 38 new_password = CharField(required=True, allow_blank=False)
uid = IntegerField(required=True) 39 39 uid = IntegerField(required=True)
token = CharField(required=True) 40 40 token = CharField(required=True)
41 41
def validate_uid(self, value): 42 42 def validate_uid(self, value):
try: 43 43 try:
User.objects.get(id=value) 44 44 User.objects.get(id=value)
return value 45 45 return value
except User.DoesNotExist: 46 46 except User.DoesNotExist:
raise serializers.ValidationError('Could not verify reset token') 47 47 raise serializers.ValidationError('Could not verify reset token')
48 48
49 49
class EmailVerificationSerializer(Serializer): 50 50 class EmailVerificationSerializer(Serializer):
confirmation_key = CharField() 51 51 confirmation_key = CharField()
52 52
53 53
class UserUpdateSerializer(Serializer): 54 54 class UserUpdateSerializer(Serializer):
old_password = CharField(required=False) 55 55 old_password = CharField(required=False)
new_password = CharField(required=False, allow_blank=False) 56 56 new_password = CharField(required=False, allow_blank=False)
57 57
def validate(self, data): 58 58 def validate(self, data):
if 'new_password' in data and 'old_password' not in data: 59 59 if 'new_password' in data and 'old_password' not in data:
raise serializers.ValidationError('old_password is required to set a new_password') 60 60 raise serializers.ValidationError('old_password is required to set a new_password')
return data 61 61 return data
62 62
63 63
class LecturePeriodSerializer(ModelSerializer): 64 64 class LecturePeriodSerializer(ModelSerializer):
class Meta: 65 65 class Meta:
model = LecturePeriod 66 66 model = LecturePeriod
exclude = 'id', 'section' 67 67 exclude = 'id', 'section'
68 68
69 69
class SectionSerializer(ModelSerializer): 70 70 class SectionSerializer(ModelSerializer):
lecture_times = CharField() 71 71 lecture_times = CharField()
short_name = CharField() 72 72 short_name = CharField()
long_name = CharField() 73 73 long_name = CharField()
can_enroll = SerializerMethodField() 74 74 can_enroll = SerializerMethodField()
is_enrolled = SerializerMethodField() 75 75 is_enrolled = SerializerMethodField()
76 76
class Meta: 77 77 class Meta:
model = Section 78 78 model = Section
79 79
def get_can_enroll(self, obj): 80 80 def get_can_enroll(self, obj):
if 'user' not in self.context: return False 81 81 if 'user' not in self.context: return False
if not obj.is_whitelisted: return True 82 82 if not obj.is_whitelisted: return True
return obj.is_user_on_whitelist(self.context['user']) 83 83 return obj.is_user_on_whitelist(self.context['user'])
84 84
def get_is_enrolled(self, obj): 85 85 def get_is_enrolled(self, obj):
if 'user' not in self.context: return False 86 86 if 'user' not in self.context: return False
return obj.is_user_enrolled(self.context['user']) 87 87 return obj.is_user_enrolled(self.context['user'])
88 88
89 89
class DeepSectionSerializer(SectionSerializer): 90 90 class DeepSectionSerializer(SectionSerializer):
lectures = LecturePeriodSerializer(source='lectureperiod_set', many=True, read_only=True) 91 91 lectures = LecturePeriodSerializer(source='lectureperiod_set', many=True, read_only=True)
92 92
93 93
class FeedRequestSerializer(Serializer): 94 94 class FeedRequestSerializer(Serializer):
page = IntegerField(min_value=1, default=1, required=False) 95 95 page = IntegerField(min_value=1, default=1, required=False)
96 96
def validate(self, attrs): 97 97 def validate(self, attrs):
if not isinstance(attrs['page'], int): 98 98 if not isinstance(attrs['page'], int):
raise serializers.ValidationError("Invalid page number") 99 99 raise serializers.ValidationError("Invalid page number")
return attrs 100 100 return attrs
101 101
102 102
class UserSerializer(ModelSerializer): 103 103 class UserSerializer(ModelSerializer):
email = EmailField(required=False) 104 104 email = EmailField(required=False)
sections = SectionSerializer(many=True) 105 105 sections = SectionSerializer(many=True)
106 106
class Meta: 107 107 class Meta:
model = User 108 108 model = User
fields = ("sections", "email", "is_confirmed", "last_login", "date_joined", 'locked') 109 109 fields = ("sections", "email", "is_confirmed", "last_login", "date_joined", 'locked')
110 110
111 111
class MaskFieldSerializer(serializers.Field): 112 112 class MaskFieldSerializer(serializers.Field):
default_error_messages = { 113 113 default_error_messages = {
'max_length': 'Ensure this field has no more than {max_length} characters.', 114 114 'max_length': 'Ensure this field has no more than {max_length} characters.',
'interval': 'Ensure this field has valid intervals.', 115 115 'interval': 'Ensure this field has valid intervals.',
'overlap': 'Ensure this field does not have overlapping intervals.' 116 116 'overlap': 'Ensure this field does not have overlapping intervals.'
} 117 117 }
118 118
def to_representation(self, value): 119 119 def to_representation(self, value):
return map(list, self._make_mask(value)) 120 120 return map(list, self._make_mask(value))
121 121
def to_internal_value(self, value): 122 122 def to_internal_value(self, value):
if not isinstance(value, list): 123 123 if not isinstance(value, list):
value = loads(value) 124 124 value = loads(value)
return self._make_mask(value) 125 125 return self._make_mask(value)
126 126
def _make_mask(self, data): 127 127 def _make_mask(self, data):
try: 128 128 try:
mask = FlashcardMask(data) 129 129 mask = FlashcardMask(data)
except ValueError: 130 130 except ValueError:
raise serializers.ValidationError("Invalid JSON for MaskField") 131 131 raise serializers.ValidationError("Invalid JSON for MaskField")
except TypeError: 132 132 except TypeError:
raise serializers.ValidationError("Invalid data for MaskField.") 133 133 raise serializers.ValidationError("Invalid data for MaskField.")
except OverlapIntervalException: 134 134 except OverlapIntervalException:
raise serializers.ValidationError("Invalid intervals for MaskField data.") 135 135 raise serializers.ValidationError("Invalid intervals for MaskField data.")
if len(mask) > 32: 136 136 if len(mask) > 32:
raise serializers.ValidationError("Too many intervals in the mask.") 137 137 raise serializers.ValidationError("Too many intervals in the mask.")
return mask 138 138 return mask
139 139
140 140
class FlashcardSerializer(ModelSerializer): 141 141 class FlashcardSerializer(ModelSerializer):
is_hidden = SerializerMethodField() 142 142 is_hidden = SerializerMethodField()
is_in_deck = SerializerMethodField() 143 143 is_in_deck = SerializerMethodField()
material_week_num = IntegerField(read_only=True) 144 144 material_week_num = IntegerField(read_only=True)
material_date = DateTimeField(default=now) 145 145 material_date = DateTimeField(default=now)
mask = MaskFieldSerializer(allow_null=True) 146 146 mask = MaskFieldSerializer(allow_null=True)
score = FloatField(read_only=True) 147 147 score = FloatField(read_only=True)
148 148
def validate_material_date(self, value): 149 149 def validate_material_date(self, value):
# TODO: make this dynamic 150 150 # TODO: make this dynamic
if QUARTER_START <= value <= QUARTER_END: 151 151 if QUARTER_START <= value <= QUARTER_END:
return value 152 152 return value
else: 153 153 else:
raise serializers.ValidationError("Material date is outside allowed range for this quarter") 154 154 raise serializers.ValidationError("Material date is outside allowed range for this quarter")
155 155
def validate_pushed(self, value): 156 156 def validate_pushed(self, value):
if value > datetime.now(): 157 157 if value > datetime.now():
raise serializers.ValidationError("Invalid creation date for the Flashcard") 158 158 raise serializers.ValidationError("Invalid creation date for the Flashcard")
return value 159 159 return value
160 160
def validate_mask(self, value): 161 161 def validate_mask(self, value):
if value is None: 162 162 if value is None:
return None 163 163 return None
if len(self.initial_data['text']) < value.max_offset(): 164 164 if len(self.initial_data['text']) < value.max_offset():
raise serializers.ValidationError("Mask out of bounds") 165 165 raise serializers.ValidationError("Mask out of bounds")
return value 166 166 return value
167 167
def get_is_hidden(self, obj): 168 168 def get_is_hidden(self, obj):
if 'user' not in self.context: return False 169 169 if 'user' not in self.context: return False
return obj.is_hidden_from(self.context['user']) 170 170 return obj.is_hidden_from(self.context['user'])
171 171
def get_is_in_deck(self, obj): 172 172 def get_is_in_deck(self, obj):
if 'user' not in self.context: return False 173 173 if 'user' not in self.context: return False
return obj.is_in_deck(self.context['user']) 174 174 return obj.is_in_deck(self.context['user'])
175 175
class Meta: 176 176 class Meta:
model = Flashcard 177 177 model = Flashcard
exclude = 'author', 'previous', 'hide_reason' 178 178 exclude = 'author', 'previous', 'hide_reason'
179 179
180 180
class FlashcardUpdateSerializer(serializers.Serializer): 181 181 class FlashcardUpdateSerializer(serializers.Serializer):
text = CharField(max_length=255, required=False) 182 182 text = CharField(max_length=255, required=False)
material_date = DateTimeField(required=False) 183 183 material_date = DateTimeField(required=False)
mask = MaskFieldSerializer(required=False) 184 184 mask = MaskFieldSerializer(required=False)
185 185
def validate_material_date(self, date): 186 186 def validate_material_date(self, date):
if date > QUARTER_END: 187 187 if date > QUARTER_END:
raise serializers.ValidationError("Invalid material_date for the flashcard") 188 188 raise serializers.ValidationError("Invalid material_date for the flashcard")
return date 189 189 return date
190 190
def validate(self, attrs): 191 191 def validate(self, attrs):
# Make sure that at least one of the attributes was passed in 192 192 # Make sure that at least one of the attributes was passed in
if not any(i in attrs for i in ['material_date', 'text', 'mask']): 193 193 if not any(i in attrs for i in ['material_date', 'text', 'mask']):
raise serializers.ValidationError("No new value passed in") 194 194 raise serializers.ValidationError("No new value passed in")
return attrs 195 195 return attrs
196 196
197 197
class QuizRequestSerializer(serializers.Serializer): 198 198 class QuizRequestSerializer(serializers.Serializer):
sections = ListField(child=IntegerField(min_value=1), required=False, default=[]) 199 199 sections = ListField(child=IntegerField(min_value=1), required=False, default=[])
material_date_begin = DateTimeField(default=QUARTER_START) 200 200 material_date_begin = DateTimeField(default=QUARTER_START)
material_date_end = DateTimeField(default=QUARTER_END) 201 201 material_date_end = DateTimeField(default=QUARTER_END)
202 202
def update(self, instance, validated_data): 203 203 def update(self, instance, validated_data):
pass 204 204 pass
205 205
def create(self, validated_data): 206 206 def create(self, validated_data):
return validated_data 207 207 return validated_data
208 208
def validate_material_date_begin(self, value): 209 209 def validate_material_date_begin(self, value):
if QUARTER_START <= value <= QUARTER_END: 210 210 if QUARTER_START <= value <= QUARTER_END:
return value 211 211 return value
raise serializers.ValidationError("Invalid begin date for the flashcard range") 212 212 raise serializers.ValidationError("Invalid begin date for the flashcard range")
213 213
def validate_material_date_end(self, value): 214 214 def validate_material_date_end(self, value):
if QUARTER_START <= value <= QUARTER_END: 215 215 if QUARTER_START <= value <= QUARTER_END:
return value 216 216 return value
raise serializers.ValidationError("Invalid end date for the flashcard range") 217 217 raise serializers.ValidationError("Invalid end date for the flashcard range")
218 218
def validate_sections(self, value): 219 219 def validate_sections(self, value):
if value is not None and not isinstance(value, Iterable): 220 220 if value is not None and not isinstance(value, Iterable):
raise serializers.ValidationError("Invalid section format. Expecting a list or no value.") 221 221 raise serializers.ValidationError("Invalid section format. Expecting a list or no value.")
if value is None or len(value) == 0: 222 222 if value is None or len(value) == 0:
return Section.objects.all() 223 223 return Section.objects.all()
section_filter = Section.objects.filter(pk__in=value) 224 224 section_filter = Section.objects.filter(pk__in=value)
if not section_filter.exists(): 225 225 if not section_filter.exists():
raise serializers.ValidationError("Those aren't valid sections") 226 226 raise serializers.ValidationError("Those aren't valid sections")
return value 227 227 return value
228 228
def validate(self, attrs): 229 229 def validate(self, attrs):