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

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
from utils.templatetags.thumbnail import thumbnail
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
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
    def _avatar(self, instance):
        placeholder = self.context['request'].build_absolute_uri(
            static('members/images/default-avatar.jpg'))
        data = {
            'full': placeholder,
            'small': placeholder,
            'medium': placeholder,
            'large': placeholder,
        }
        if instance.member and instance.member.profile.photo:
            data['full'] = self.context['request'].build_absolute_uri(
                '%s%s' % (settings.MEDIA_URL, instance.member.profile.photo))
            data['small'] = self.context['request'].build_absolute_uri(
                thumbnail(instance.member.profile.photo, '110x110', 1))
            data['medium'] = self.context['request'].build_absolute_uri(
                thumbnail(instance.member.profile.photo, '220x220', 1))
            data['large'] = self.context['request'].build_absolute_uri(
                thumbnail(instance.member.profile.photo, '800x800', 1))
        return data

264
265
266
267
268
269

class RegistrationSerializer(serializers.ModelSerializer):
    information_fields = None

    class Meta:
        model = Registration
270
        fields = ('pk', 'member', 'name', 'photo', 'avatar', 'registered_on',
271
                  'is_late_cancellation', 'is_cancelled',
272
                  'queue_position', 'fields')
273
274
275

    name = serializers.SerializerMethodField('_name')
    photo = serializers.SerializerMethodField('_photo')
276
    avatar = serializers.SerializerMethodField('_avatar')
277
278
279
280
281
282
283
    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)
284
    fields = serializers.HiddenField(default='')
285
286
287
288
289

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

290
    def _is_cancelled(self, instance):
291
292
293
294
295
        return instance.date_cancelled is not None

    def _queue_position(self, instance):
        pos = instance.queue_position
        return pos if pos > 0 else None
296
297
298

    def _member(self, instance):
        if instance.member:
299
            return instance.member.pk
300
301
302
303
        return None

    def _name(self, instance):
        if instance.member:
304
            return instance.member.profile.display_name()
305
306
307
        return instance.name

    def _photo(self, instance):
308
        if instance.member and instance.member.profile.photo:
309
            return self.context['request'].build_absolute_uri(
310
                '%s%s' % (settings.MEDIA_URL, instance.member.profile.photo))
311
        else:
312
            return self.context['request'].build_absolute_uri(
Sébastiaan Versteeg's avatar
Sébastiaan Versteeg committed
313
                static('members/images/default-avatar.jpg'))
314

315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
    def _avatar(self, instance):
        placeholder = self.context['request'].build_absolute_uri(
            static('members/images/default-avatar.jpg'))
        data = {
            'full': placeholder,
            'small': placeholder,
            'medium': placeholder,
            'large': placeholder,
        }
        if instance.member and instance.member.profile.photo:
            data['full'] = self.context['request'].build_absolute_uri(
                '%s%s' % (settings.MEDIA_URL, instance.member.profile.photo))
            data['small'] = self.context['request'].build_absolute_uri(
                thumbnail(instance.member.profile.photo, '110x110', 1))
            data['medium'] = self.context['request'].build_absolute_uri(
                thumbnail(instance.member.profile.photo, '220x220', 1))
            data['large'] = self.context['request'].build_absolute_uri(
                thumbnail(instance.member.profile.photo, '800x800', 1))
        return data

335
336
337
338
339
    def __init__(self, instance=None, data=empty, **kwargs):
        super().__init__(instance, data, **kwargs)
        try:
            if instance:
                self.information_fields = services.registration_fields(
340
                    instance.member, instance.event)
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
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
        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)