serializers.py 13.3 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

Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
9
from thaliawebsite.api.services import create_image_thumbnail_dict
10
11
12
from events import services
from events.exceptions import RegistrationError
from events.models import Event, Registration, RegistrationInformationField
13
from pizzas.models import PizzaEvent
14
from thaliawebsite.settings import settings
15
16
17
18
19
20
21


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

    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')
33
34
35
    backgroundColor = serializers.SerializerMethodField('_background_color')
    textColor = serializers.SerializerMethodField('_text_color')
    blank = serializers.SerializerMethodField('_target_blank')
36
    registered = serializers.SerializerMethodField('_registered')
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

    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):
57
        return unescape(strip_tags(instance.description))
58
59
60
61
62
63
64
65
66
67

    def _background_color(self, instance):
        pass

    def _text_color(self, instance):
        pass

    def _target_blank(self, instance):
        return False

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

71

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

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

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


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
100
101


102
class EventRetrieveSerializer(serializers.ModelSerializer):
Gijs Hendriksen's avatar
Gijs Hendriksen committed
103
104
    class Meta:
        model = Event
105
106
107
108
109
110
        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
111

112
    description = serializers.SerializerMethodField('_description')
113
114
115
116
117
    user_registration = serializers.SerializerMethodField('_user_registration')
    num_participants = serializers.SerializerMethodField('_num_participants')
    registration_allowed = serializers.SerializerMethodField(
        '_registration_allowed')
    has_fields = serializers.SerializerMethodField('_has_fields')
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
145
146
    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
147

148
    def _description(self, instance):
149
        return unescape(strip_tags(instance.description))
150

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

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

    def _registration_allowed(self, instance):
166
167
168
        member = self.context['request'].member
        return (member.has_active_membership and
                member.can_attend_events)
169
170
171
172

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

173

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

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

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

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

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

198

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

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

216
    def _is_late_cancellation(self, instance):
217
        return instance.is_late_cancellation()
218
219

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

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

226
227
    def _member(self, instance):
        if instance.member:
228
            return instance.member.pk
229
        return None
230

231
232
    def _name(self, instance):
        if instance.member:
233
            return instance.member.profile.display_name()
234
235
236
        return instance.name

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

244
245
246
    def _avatar(self, instance):
        placeholder = self.context['request'].build_absolute_uri(
            static('members/images/default-avatar.jpg'))
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
247
        file = None
248
        if instance.member and instance.member.profile.photo:
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
249
250
251
252
            file = instance.member.profile.photo
        return create_image_thumbnail_dict(
            self.context['request'], file, placeholder=placeholder,
            size_large='800x800')
253

254
255
256
257
258
259

class RegistrationSerializer(serializers.ModelSerializer):
    information_fields = None

    class Meta:
        model = Registration
260
        fields = ('pk', 'member', 'name', 'photo', 'avatar', 'registered_on',
261
                  'is_late_cancellation', 'is_cancelled',
262
                  'queue_position', 'fields')
263
264
265

    name = serializers.SerializerMethodField('_name')
    photo = serializers.SerializerMethodField('_photo')
266
    avatar = serializers.SerializerMethodField('_avatar')
267
268
269
270
271
272
273
    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)
274
    fields = serializers.HiddenField(default='')
275
276
277
278
279

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

280
    def _is_cancelled(self, instance):
281
282
283
284
285
        return instance.date_cancelled is not None

    def _queue_position(self, instance):
        pos = instance.queue_position
        return pos if pos > 0 else None
286
287
288

    def _member(self, instance):
        if instance.member:
289
            return instance.member.pk
290
291
292
293
        return None

    def _name(self, instance):
        if instance.member:
294
            return instance.member.profile.display_name()
295
296
297
        return instance.name

    def _photo(self, instance):
298
        if instance.member and instance.member.profile.photo:
299
            return self.context['request'].build_absolute_uri(
300
                '%s%s' % (settings.MEDIA_URL, instance.member.profile.photo))
301
        else:
302
            return self.context['request'].build_absolute_uri(
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
303
                static('members/images/default-avatar.jpg'))
304

305
306
307
    def _avatar(self, instance):
        placeholder = self.context['request'].build_absolute_uri(
            static('members/images/default-avatar.jpg'))
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
308
        file = None
309
        if instance.member and instance.member.profile.photo:
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
310
311
312
313
            file = instance.member.profile.photo
        return create_image_thumbnail_dict(
            self.context['request'], file, placeholder=placeholder,
            size_large='800x800')
314

315
316
317
318
319
    def __init__(self, instance=None, data=empty, **kwargs):
        super().__init__(instance, data, **kwargs)
        try:
            if instance:
                self.information_fields = services.registration_fields(
320
                    instance.member, instance.event)
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
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
        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)