serializers.py 12.2 KB
Newer Older
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
1
from django.templatetags.static import static
2
from django.urls import reverse
3
from django.utils import timezone
4
from django.utils.html import strip_tags
5
from html import unescape
6
from rest_framework import serializers
7
from rest_framework.fields import empty
8

9
10
11
from events import services
from events.exceptions import RegistrationError
from events.models import Event, Registration, RegistrationInformationField
12
from pizzas.models import PizzaEvent
13
from thaliawebsite.settings import settings
14
15
16
17
18
19
20


class CalenderJSSerializer(serializers.ModelSerializer):
    class Meta:
        fields = (
            'start', 'end', 'all_day', 'is_birthday',
            'url', 'title', 'description',
21
22
            'backgroundColor', 'textColor', 'blank',
            'registered'
23
24
25
26
27
28
29
30
31
        )

    start = serializers.SerializerMethodField('_start')
    end = serializers.SerializerMethodField('_end')
    all_day = serializers.SerializerMethodField('_all_day')
    is_birthday = serializers.SerializerMethodField('_is_birthday')
    url = serializers.SerializerMethodField('_url')
    title = serializers.SerializerMethodField('_title')
    description = serializers.SerializerMethodField('_description')
32
33
34
    backgroundColor = serializers.SerializerMethodField('_background_color')
    textColor = serializers.SerializerMethodField('_text_color')
    blank = serializers.SerializerMethodField('_target_blank')
35
    registered = serializers.SerializerMethodField('_registered')
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55

    def _start(self, instance):
        return timezone.localtime(instance.start)

    def _end(self, instance):
        return timezone.localtime(instance.end)

    def _all_day(self, instance):
        return False

    def _is_birthday(self, instance):
        return False

    def _url(self, instance):
        raise NotImplementedError

    def _title(self, instance):
        return instance.title

    def _description(self, instance):
56
        return unescape(strip_tags(instance.description))
57
58
59
60
61
62
63
64
65
66

    def _background_color(self, instance):
        pass

    def _text_color(self, instance):
        pass

    def _target_blank(self, instance):
        return False

67
68
69
    def _registered(self, instance):
        return None

70

71
class EventCalenderJSSerializer(CalenderJSSerializer):
72
73
74
75
    class Meta(CalenderJSSerializer.Meta):
        model = Event

    def _url(self, instance):
76
        return reverse('events:event', kwargs={'pk': instance.id})
77
78
79

    def _registered(self, instance):
        try:
80
            return services.is_user_registered(instance, self.context['user'])
81
82
        except AttributeError:
            return None
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97


class UnpublishedEventSerializer(CalenderJSSerializer):
    class Meta(CalenderJSSerializer.Meta):
        model = Event

    def _background_color(self, instance):
        return "#888888"

    def _text_color(self, instance):
        return "white"

    def _url(self, instance):
        return reverse('events:admin-details', kwargs={
            'event_id': instance.id})
Gijs Hendriksen's avatar
Gijs Hendriksen committed
98
99


100
class EventRetrieveSerializer(serializers.ModelSerializer):
Gijs Hendriksen's avatar
Gijs Hendriksen committed
101
102
    class Meta:
        model = Event
103
104
105
106
107
108
        fields = ('pk', 'title', 'description', 'start', 'end', 'organiser',
                  'category', 'registration_start', 'registration_end',
                  'cancel_deadline', 'location', 'map_location', 'price',
                  'fine', 'max_participants', 'num_participants', 'status',
                  'user_registration', 'registration_allowed',
                  'no_registration_message', 'has_fields')
AuckeBos's avatar
AuckeBos committed
109

110
    description = serializers.SerializerMethodField('_description')
111
112
113
114
115
    user_registration = serializers.SerializerMethodField('_user_registration')
    num_participants = serializers.SerializerMethodField('_num_participants')
    registration_allowed = serializers.SerializerMethodField(
        '_registration_allowed')
    has_fields = serializers.SerializerMethodField('_has_fields')
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
    status = serializers.SerializerMethodField('_status')  # DEPRECATED

    REGISTRATION_NOT_NEEDED = -1
    REGISTRATION_NOT_YET_OPEN = 0
    REGISTRATION_OPEN = 1
    REGISTRATION_OPEN_NO_CANCEL = 2
    REGISTRATION_CLOSED = 3
    REGISTRATION_CLOSED_CANCEL_ONLY = 4

    """ DEPRECATED """

    def _status(self, instance):
        now = timezone.now()
        if instance.registration_start or instance.registration_end:
            if now <= instance.registration_start:
                return self.REGISTRATION_NOT_YET_OPEN
            elif (instance.registration_end <= now
                    < instance.cancel_deadline):
                return self.REGISTRATION_CLOSED_CANCEL_ONLY
            elif (instance.cancel_deadline <= now <
                    instance.registration_end):
                return self.REGISTRATION_OPEN_NO_CANCEL
            elif (now >= instance.registration_end and
                    now >= instance.cancel_deadline):
                return self.REGISTRATION_CLOSED
            else:
                return self.REGISTRATION_OPEN
        else:
            return self.REGISTRATION_NOT_NEEDED
AuckeBos's avatar
AuckeBos committed
145

146
    def _description(self, instance):
147
        return unescape(strip_tags(instance.description))
148

149
    def _num_participants(self, instance):
150
        if (instance.max_participants and
151
                instance.participants.count() > instance.max_participants):
152
            return instance.max_participants
153
        return instance.participants.count()
154
155
156
157
158

    def _user_registration(self, instance):
        try:
            reg = instance.registration_set.get(
                member=self.context['request'].user.member)
159
            return RegistrationListSerializer(reg, context=self.context).data
160
161
162
163
164
165
166
167
168
169
170
171
        except Registration.DoesNotExist:
            return None

    def _registration_allowed(self, instance):
        member = self.context['request'].user.member
        return (member is not None and
                member.current_membership is not None and
                member.can_attend_events)

    def _has_fields(self, instance):
        return instance.has_fields()

172

173
class EventListSerializer(serializers.ModelSerializer):
AuckeBos's avatar
AuckeBos committed
174
175
    class Meta:
        model = Event
176
        fields = ('pk', 'title', 'description', 'start', 'end',
177
                  'location', 'price', 'registered', 'pizza')
178
179

    description = serializers.SerializerMethodField('_description')
180
    registered = serializers.SerializerMethodField('_registered')
181
    pizza = serializers.SerializerMethodField('_pizza')
182
183

    def _description(self, instance):
184
        return unescape(strip_tags(instance.description))
185
186
187

    def _registered(self, instance):
        try:
188
189
            return services.is_user_registered(
                instance, self.context['request'].user)
190
191
192
        except AttributeError:
            return None

193
194
195
196
    def _pizza(self, instance):
        pizza_events = PizzaEvent.objects.filter(event=instance)
        return pizza_events.exists()

197

198
class RegistrationListSerializer(serializers.ModelSerializer):
199
200
    class Meta:
        model = Registration
201
202
        fields = ('pk', 'member', 'name', 'photo', 'registered_on',
                  'is_late_cancellation', 'is_cancelled', 'queue_position')
203
204
205
206

    name = serializers.SerializerMethodField('_name')
    photo = serializers.SerializerMethodField('_photo')
    member = serializers.SerializerMethodField('_member')
207
    registered_on = serializers.DateTimeField(source='date')
208
209
210
211
    is_cancelled = serializers.SerializerMethodField('_is_cancelled')
    is_late_cancellation = serializers.SerializerMethodField(
        '_is_late_cancellation')
    queue_position = serializers.SerializerMethodField(
212
        '_queue_position', read_only=False)
213

214
    def _is_late_cancellation(self, instance):
215
        return instance.is_late_cancellation()
216
217

    def _queue_position(self, instance):
218
219
220
221
222
        pos = instance.queue_position
        return pos if pos > 0 else None

    def _is_cancelled(self, instance):
        return instance.date_cancelled is not None
223

224
225
    def _member(self, instance):
        if instance.member:
226
            return instance.member.user.pk
227
        return None
228

229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
    def _name(self, instance):
        if instance.member:
            return instance.member.display_name()
        return instance.name

    def _photo(self, instance):
        if instance.member and instance.member.photo:
            return self.context['request'].build_absolute_uri(
                '%s%s' % (settings.MEDIA_URL, instance.member.photo))
        else:
            return self.context['request'].build_absolute_uri(
                static('members/images/default-avatar.jpg'))


class RegistrationSerializer(serializers.ModelSerializer):
    information_fields = None

    class Meta:
        model = Registration
        fields = ('pk', 'member', 'name', 'photo', 'registered_on',
                  'is_late_cancellation', 'is_cancelled',
250
                  'queue_position', 'fields')
251
252
253
254
255
256
257
258
259
260

    name = serializers.SerializerMethodField('_name')
    photo = serializers.SerializerMethodField('_photo')
    member = serializers.SerializerMethodField('_member')
    registered_on = serializers.DateTimeField(source='date', read_only=True)
    is_cancelled = serializers.SerializerMethodField('_is_cancelled')
    is_late_cancellation = serializers.SerializerMethodField(
        '_is_late_cancellation')
    queue_position = serializers.SerializerMethodField(
        '_queue_position', read_only=False)
261
    fields = serializers.HiddenField(default='')
262
263
264
265
266

    def _is_late_cancellation(self, instance):
        val = instance.is_late_cancellation()
        return False if val is None else val

267
    def _is_cancelled(self, instance):
268
269
270
271
272
        return instance.date_cancelled is not None

    def _queue_position(self, instance):
        pos = instance.queue_position
        return pos if pos > 0 else None
273
274
275

    def _member(self, instance):
        if instance.member:
276
            return instance.member.pk
277
278
279
280
281
282
283
284
285
        return None

    def _name(self, instance):
        if instance.member:
            return instance.member.display_name()
        return instance.name

    def _photo(self, instance):
        if instance.member and instance.member.photo:
286
287
            return self.context['request'].build_absolute_uri(
                '%s%s' % (settings.MEDIA_URL, instance.member.photo))
288
        else:
289
            return self.context['request'].build_absolute_uri(
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
290
                static('members/images/default-avatar.jpg'))
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346

    def __init__(self, instance=None, data=empty, **kwargs):
        super().__init__(instance, data, **kwargs)
        try:
            if instance:
                self.information_fields = services.registration_fields(
                    instance.member.user, instance.event)
        except RegistrationError:
            pass

    def get_fields(self):
        fields = super().get_fields()

        if self.information_fields:
            for key, field in self.information_fields.items():
                key = 'fields[{}]'.format(key)
                field_type = field['type']

                if field_type == RegistrationInformationField.BOOLEAN_FIELD:
                    fields[key] = serializers.BooleanField(
                        required=False,
                        write_only=True
                    )
                elif field_type == RegistrationInformationField.INTEGER_FIELD:
                    fields[key] = serializers.IntegerField(
                        required=field['required'],
                        write_only=True
                    )
                elif field_type == RegistrationInformationField.TEXT_FIELD:
                    fields[key] = serializers.CharField(
                        required=field['required'],
                        write_only=True
                    )

                fields[key].label = field['label']
                fields[key].help_text = field['description']
                fields[key].initial = field['value']
                fields[key].default = field['value']

                try:
                    if key in self.information_fields:
                        fields[key].initial = self.validated_data[key]
                except AssertionError:
                    pass

        return fields

    def to_representation(self, instance):
        data = super().to_representation(instance)
        data['fields'] = self.information_fields
        return data

    def field_values(self):
        return ((name[7:len(name) - 1], value)
                for name, value in self.validated_data.items()
                if "info_field" in name)