Commit 9a6e3424bee6359a5806b66edde0406ee40e57f3

Authored by Rohan Rangray
1 parent 67b19d6d94
Exists in master

Wrote the MaskField serializer field.

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

flashcards/serializers.py View file @ 9a6e342
from django.utils.datetime_safe import datetime 1 1 from django.utils.datetime_safe import datetime
from flashcards.models import Section, LecturePeriod, User, Flashcard 2 2 from flashcards.models import Section, LecturePeriod, User, Flashcard
3 from flashcards.validators import FlashcardMask, OverlapIntervalException
from rest_framework import serializers 3 4 from rest_framework import serializers
from rest_framework.fields import EmailField, BooleanField, CharField, IntegerField 4 5 from rest_framework.fields import EmailField, BooleanField, CharField, IntegerField
from rest_framework.relations import HyperlinkedRelatedField 5 6 from rest_framework.relations import HyperlinkedRelatedField
from rest_framework.serializers import ModelSerializer, Serializer 6 7 from rest_framework.serializers import ModelSerializer, Serializer
from rest_framework.validators import UniqueValidator 7 8 from rest_framework.validators import UniqueValidator
from json import dumps, loads 8 9 from json import dumps, loads
9 10
10 11
class EmailSerializer(Serializer): 11 12 class EmailSerializer(Serializer):
email = EmailField(required=True) 12 13 email = EmailField(required=True)
13 14
14 15
class EmailPasswordSerializer(EmailSerializer): 15 16 class EmailPasswordSerializer(EmailSerializer):
password = CharField(required=True) 16 17 password = CharField(required=True)
17 18
18 19
class RegistrationSerializer(EmailPasswordSerializer): 19 20 class RegistrationSerializer(EmailPasswordSerializer):
email = EmailField(required=True, validators=[UniqueValidator(queryset=User.objects.all())]) 20 21 email = EmailField(required=True, validators=[UniqueValidator(queryset=User.objects.all())])
21 22
22 23
class PasswordResetRequestSerializer(EmailSerializer): 23 24 class PasswordResetRequestSerializer(EmailSerializer):
def validate_email(self, value): 24 25 def validate_email(self, value):
try: 25 26 try:
User.objects.get(email=value) 26 27 User.objects.get(email=value)
return value 27 28 return value
except User.DoesNotExist: 28 29 except User.DoesNotExist:
raise serializers.ValidationError('No user exists with that email') 29 30 raise serializers.ValidationError('No user exists with that email')
30 31
31 32
class PasswordResetSerializer(Serializer): 32 33 class PasswordResetSerializer(Serializer):
new_password = CharField(required=True, allow_blank=False) 33 34 new_password = CharField(required=True, allow_blank=False)
uid = IntegerField(required=True) 34 35 uid = IntegerField(required=True)
token = CharField(required=True) 35 36 token = CharField(required=True)
36 37
def validate_uid(self, value): 37 38 def validate_uid(self, value):
try: 38 39 try:
User.objects.get(id=value) 39 40 User.objects.get(id=value)
return value 40 41 return value
except User.DoesNotExist: 41 42 except User.DoesNotExist:
raise serializers.ValidationError('Could not verify reset token') 42 43 raise serializers.ValidationError('Could not verify reset token')
43 44
44 45
class UserUpdateSerializer(Serializer): 45 46 class UserUpdateSerializer(Serializer):
old_password = CharField(required=False) 46 47 old_password = CharField(required=False)
new_password = CharField(required=False, allow_blank=False) 47 48 new_password = CharField(required=False, allow_blank=False)
confirmation_key = CharField(required=False) 48 49 confirmation_key = CharField(required=False)
# reset_token = CharField(required=False) 49 50 # reset_token = CharField(required=False)
50 51
def validate(self, data): 51 52 def validate(self, data):
if 'new_password' in data and 'old_password' not in data: 52 53 if 'new_password' in data and 'old_password' not in data:
raise serializers.ValidationError('old_password is required to set a new_password') 53 54 raise serializers.ValidationError('old_password is required to set a new_password')
return data 54 55 return data
55 56
56 57
class Password(Serializer): 57 58 class Password(Serializer):
email = EmailField(required=True) 58 59 email = EmailField(required=True)
password = CharField(required=True) 59 60 password = CharField(required=True)
60 61
61 62
class LecturePeriodSerializer(ModelSerializer): 62 63 class LecturePeriodSerializer(ModelSerializer):
class Meta: 63 64 class Meta:
model = LecturePeriod 64 65 model = LecturePeriod
exclude = 'id', 'section' 65 66 exclude = 'id', 'section'
66 67
67 68
class SectionSerializer(ModelSerializer): 68 69 class SectionSerializer(ModelSerializer):
lectures = LecturePeriodSerializer(source='lectureperiod_set', many=True, read_only=True) 69 70 lectures = LecturePeriodSerializer(source='lectureperiod_set', many=True, read_only=True)
70 71
class Meta: 71 72 class Meta:
model = Section 72 73 model = Section
73 74
74 75
class UserSerializer(ModelSerializer): 75 76 class UserSerializer(ModelSerializer):
email = EmailField(required=False) 76 77 email = EmailField(required=False)
sections = HyperlinkedRelatedField(queryset=Section.objects.all(), many=True, view_name='section-detail') 77 78 sections = HyperlinkedRelatedField(queryset=Section.objects.all(), many=True, view_name='section-detail')
is_confirmed = BooleanField() 78 79 is_confirmed = BooleanField()
79 80
class Meta: 80 81 class Meta:
model = User 81 82 model = User
fields = ("sections", "email", "is_confirmed", "last_login", "date_joined") 82 83 fields = ("sections", "email", "is_confirmed", "last_login", "date_joined")
83 84
84 85
class MaskFieldSerializer(serializers.Field): 85 86 class MaskFieldSerializer(serializers.Field):
default_error_messages = { 86 87 default_error_messages = {
'max_length': 'Ensure this field has no more than {max_length} characters.', 87 88 'max_length': 'Ensure this field has no more than {max_length} characters.',
'interval': 'Ensure this field has valid intervals.', 88 89 'interval': 'Ensure this field has valid intervals.',
'overlap': 'Ensure this field does not have overlapping intervals.' 89 90 'overlap': 'Ensure this field does not have overlapping intervals.'
} 90 91 }
91 92
def to_representation(self, value): 92 93 def to_representation(self, value):
if not isinstance(value, set) or not all([isinstance(i, tuple) for i in value]): 93 94 return dumps(list(self._make_mask(value)))
raise serializers.ValidationError("Invalid MaskField.") 94
return dumps(list(value)) 95
96 95
def to_internal_value(self, data): 97 96 def to_internal_value(self, value):
97 return self._make_mask(value)
98
99 def _make_mask(self, data):
try: 98 100 try:
intervals = loads(data) 99 101 mask = FlashcardMask(loads(data))
if not isinstance(intervals, list) or len(intervals) > 32 \ 100
or not all([isinstance(i, list) and len(i) == 2 for i in intervals]): 101
raise ValueError 102
except ValueError: 103 102 except ValueError:
raise serializers.ValidationError("Invalid JSON for MaskField") 104 103 raise serializers.ValidationError("Invalid JSON for MaskField")
return set([tuple(i) for i in intervals]) 105 104 except TypeError:
105 raise serializers.ValidationError("Invalid data for MaskField.")
106 except OverlapIntervalException:
107 raise serializers.ValidationError("Invalid intervals for MaskField data.")
108 if len(mask) > 32:
109 raise serializers.ValidationError("Too many intervals in the mask.")
110 return mask
106 111
107 112
class FlashcardSerializer(ModelSerializer): 108 113 class FlashcardSerializer(ModelSerializer):
is_hidden = BooleanField(read_only=True) 109 114 is_hidden = BooleanField(read_only=True)
hide_reason = CharField(read_only=True) 110 115 hide_reason = CharField(read_only=True)
mask = MaskFieldSerializer() 111 116 mask = MaskFieldSerializer()
112 117
def validate_material_date(self, value): 113 118 def validate_material_date(self, value):
# TODO: make this dynamic 114 119 # TODO: make this dynamic
quarter_start = datetime(2015, 3, 15) 115 120 quarter_start = datetime(2015, 3, 15)
quarter_end = datetime(2015, 6, 15) 116 121 quarter_end = datetime(2015, 6, 15)
if quarter_start <= value <= quarter_end: 117 122 if quarter_start <= value <= quarter_end:
return value 118 123 return value