api: move serializers to new file (#56083)

This commit is contained in:
Valentin Deniaud 2021-08-05 17:07:41 +02:00
parent 9d90cb6618
commit 95e2618863
2 changed files with 104 additions and 106 deletions

93
chrono/api/serializers.py Normal file
View File

@ -0,0 +1,93 @@
from django.utils.translation import ugettext_lazy as _
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
from chrono.agendas.models import Booking
class StringOrListField(serializers.ListField):
def to_internal_value(self, data):
if isinstance(data, str):
data = [s.strip() for s in data.split(',') if s.strip()]
return super().to_internal_value(data)
class SlotSerializer(serializers.Serializer):
label = serializers.CharField(max_length=250, allow_blank=True)
user_external_id = serializers.CharField(max_length=250, allow_blank=True)
user_name = serializers.CharField(max_length=250, allow_blank=True) # compatibility
user_first_name = serializers.CharField(max_length=250, allow_blank=True)
user_last_name = serializers.CharField(max_length=250, allow_blank=True)
user_display_label = serializers.CharField(max_length=250, allow_blank=True)
user_email = serializers.CharField(max_length=250, allow_blank=True)
user_phone_number = serializers.CharField(max_length=16, allow_blank=True)
exclude_user = serializers.BooleanField(default=False)
events = serializers.CharField(max_length=16, allow_blank=True)
form_url = serializers.CharField(max_length=250, allow_blank=True)
backoffice_url = serializers.URLField(allow_blank=True)
cancel_callback_url = serializers.URLField(allow_blank=True)
count = serializers.IntegerField(min_value=1)
cancel_booking_id = serializers.CharField(max_length=250, allow_blank=True, allow_null=True)
force_waiting_list = serializers.BooleanField(default=False)
use_color_for = serializers.CharField(max_length=250, allow_blank=True)
class SlotsSerializer(SlotSerializer):
slots = StringOrListField(required=True, child=serializers.CharField(max_length=160, allow_blank=False))
def validate(self, attrs):
super().validate(attrs)
if not attrs.get('slots'):
raise serializers.ValidationError({'slots': _('This field is required.')})
return attrs
class EventsSlotsSerializer(SlotSerializer):
slots = StringOrListField(required=True, child=serializers.CharField(max_length=160))
def validate(self, attrs):
super().validate(attrs)
if not 'slots' in attrs:
raise serializers.ValidationError({'slots': _('This field is required.')})
if not attrs.get('user_external_id'):
raise serializers.ValidationError({'user_external_id': _('This field is required.')})
return attrs
class BookingSerializer(serializers.ModelSerializer):
user_absence_reason = serializers.CharField(required=False, allow_blank=True, allow_null=True)
class Meta:
model = Booking
fields = ['id', 'in_waiting_list', 'user_was_present', 'user_absence_reason', 'extra_data']
read_only_fields = ['id', 'in_waiting_list']
def validate_user_absence_reason(self, value):
if not value:
return ''
if not self.instance.event.agenda.absence_reasons_group:
raise serializers.ValidationError(_('unknown absence reason'))
reasons_qs = self.instance.event.agenda.absence_reasons_group.absence_reasons
try:
reason = reasons_qs.get(slug=value)
value = reason.label
except AbsenceReason.DoesNotExist:
if not reasons_qs.filter(label=value).exists():
raise serializers.ValidationError(_('unknown absence reason'))
return value
class ResizeSerializer(serializers.Serializer):
count = serializers.IntegerField(min_value=1)
class StatisticsFiltersSerializer(serializers.Serializer):
time_interval = serializers.ChoiceField(choices=('day', _('Day')), default='day')
start = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
end = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
category = serializers.SlugField(required=False, allow_blank=False, max_length=256)
agenda = serializers.SlugField(required=False, allow_blank=False, max_length=256)
group_by = serializers.SlugField(required=False, allow_blank=False, max_length=256)

View File

@ -35,7 +35,7 @@ from django.utils.timezone import is_naive, localtime, make_aware, now
from django.utils.translation import gettext_noop
from django.utils.translation import ugettext_lazy as _
from django_filters import rest_framework as filters
from rest_framework import permissions, serializers, status
from rest_framework import permissions, status
from rest_framework.exceptions import ValidationError
from rest_framework.generics import ListAPIView
from rest_framework.views import APIView
@ -51,6 +51,7 @@ from chrono.agendas.models import (
MeetingType,
TimePeriodException,
)
from chrono.api import serializers
from chrono.api.utils import APIError, Response
from chrono.interval import IntervalSet
@ -1117,67 +1118,9 @@ class AgendaResourceList(APIView):
agenda_resource_list = AgendaResourceList.as_view()
class SlotSerializer(serializers.Serializer):
"""
payload to fill one slot. The slot (event id) is in the URL.
"""
label = serializers.CharField(max_length=250, allow_blank=True)
user_external_id = serializers.CharField(max_length=250, allow_blank=True)
user_name = serializers.CharField(max_length=250, allow_blank=True) # compatibility
user_first_name = serializers.CharField(max_length=250, allow_blank=True)
user_last_name = serializers.CharField(max_length=250, allow_blank=True)
user_display_label = serializers.CharField(max_length=250, allow_blank=True)
user_email = serializers.CharField(max_length=250, allow_blank=True)
user_phone_number = serializers.CharField(max_length=16, allow_blank=True)
exclude_user = serializers.BooleanField(default=False)
events = serializers.CharField(max_length=16, allow_blank=True)
form_url = serializers.CharField(max_length=250, allow_blank=True)
backoffice_url = serializers.URLField(allow_blank=True)
cancel_callback_url = serializers.URLField(allow_blank=True)
count = serializers.IntegerField(min_value=1)
cancel_booking_id = serializers.CharField(max_length=250, allow_blank=True, allow_null=True)
force_waiting_list = serializers.BooleanField(default=False)
use_color_for = serializers.CharField(max_length=250, allow_blank=True)
class StringOrListField(serializers.ListField):
def to_internal_value(self, data):
if isinstance(data, str):
data = [s.strip() for s in data.split(',') if s.strip()]
return super().to_internal_value(data)
class SlotsSerializer(SlotSerializer):
"""
payload to fill multiple slots: same as SlotSerializer, but the
slots list is in the payload.
"""
slots = StringOrListField(required=True, child=serializers.CharField(max_length=160, allow_blank=False))
def validate(self, attrs):
super().validate(attrs)
if not attrs.get('slots'):
raise serializers.ValidationError({'slots': _('This field is required.')})
return attrs
class EventsSlotsSerializer(SlotSerializer):
slots = StringOrListField(required=True, child=serializers.CharField(max_length=160))
def validate(self, attrs):
super().validate(attrs)
if not 'slots' in attrs:
raise serializers.ValidationError({'slots': _('This field is required.')})
if not attrs.get('user_external_id'):
raise serializers.ValidationError({'user_external_id': _('This field is required.')})
return attrs
class Fillslots(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = SlotsSerializer
serializer_class = serializers.SlotsSerializer
def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
return self.fillslot(request=request, agenda_identifier=agenda_identifier, format=format)
@ -1539,7 +1482,7 @@ fillslots = Fillslots.as_view()
class Fillslot(Fillslots):
serializer_class = SlotSerializer
serializer_class = serializers.SlotSerializer
def post(self, request, agenda_identifier=None, event_identifier=None, format=None):
return self.fillslot(
@ -1555,7 +1498,7 @@ fillslot = Fillslot.as_view()
class RecurringFillslots(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = EventsSlotsSerializer
serializer_class = serializers.EventsSlotsSerializer
def post(self, request, agenda_identifier):
if not settings.ENABLE_RECURRING_EVENT_BOOKING:
@ -1657,7 +1600,7 @@ recurring_fillslots = RecurringFillslots.as_view()
class EventsFillslots(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = EventsSlotsSerializer
serializer_class = serializers.EventsSlotsSerializer
def post(self, request, agenda_identifier):
agenda = get_object_or_404(Agenda, slug=agenda_identifier, kind='events')
@ -1729,32 +1672,6 @@ class EventsFillslots(APIView):
events_fillslots = EventsFillslots.as_view()
class BookingSerializer(serializers.ModelSerializer):
user_absence_reason = serializers.CharField(required=False, allow_blank=True, allow_null=True)
class Meta:
model = Booking
fields = ['id', 'in_waiting_list', 'user_was_present', 'user_absence_reason', 'extra_data']
read_only_fields = ['id', 'in_waiting_list']
def validate_user_absence_reason(self, value):
if not value:
return ''
if not self.instance.event.agenda.absence_reasons_group:
raise serializers.ValidationError(_('unknown absence reason'))
reasons_qs = self.instance.event.agenda.absence_reasons_group.absence_reasons
try:
reason = reasons_qs.get(slug=value)
value = reason.label
except AbsenceReason.DoesNotExist:
if not reasons_qs.filter(label=value).exists():
raise serializers.ValidationError(_('unknown absence reason'))
return value
class BookingFilter(filters.FilterSet):
agenda = filters.CharFilter(field_name='event__agenda__slug', lookup_expr='exact')
category = filters.CharFilter(field_name='event__agenda__category__slug', lookup_expr='exact')
@ -1781,7 +1698,7 @@ class BookingFilter(filters.FilterSet):
class BookingsAPI(ListAPIView):
filter_backends = (filters.DjangoFilterBackend,)
serializer_class = BookingSerializer
serializer_class = serializers.BookingSerializer
filterset_class = BookingFilter
def get(self, request, *args, **kwargs):
@ -1817,7 +1734,7 @@ bookings = BookingsAPI.as_view()
class BookingAPI(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = BookingSerializer
serializer_class = serializers.BookingSerializer
def initial(self, request, *args, **kwargs):
super().initial(request, *args, **kwargs)
@ -2055,10 +1972,6 @@ class AnonymizeBooking(APIView):
anonymize_booking = AnonymizeBooking.as_view()
class ResizeSerializer(serializers.Serializer):
count = serializers.IntegerField(min_value=1)
class ResizeBooking(APIView):
"""
Resize a booking.
@ -2070,7 +1983,7 @@ class ResizeBooking(APIView):
"""
permission_classes = (permissions.IsAuthenticated,)
serializer_class = ResizeSerializer
serializer_class = serializers.ResizeSerializer
def post(self, request, booking_pk=None, format=None):
serializer = self.serializer_class(data=request.data)
@ -2361,20 +2274,12 @@ class StatisticsList(APIView):
statistics_list = StatisticsList.as_view()
class StatisticsFiltersSerializer(serializers.Serializer):
time_interval = serializers.ChoiceField(choices=('day', _('Day')), default='day')
start = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
end = serializers.DateTimeField(required=False, input_formats=['iso-8601', '%Y-%m-%d'])
category = serializers.SlugField(required=False, allow_blank=False, max_length=256)
agenda = serializers.SlugField(required=False, allow_blank=False, max_length=256)
group_by = serializers.SlugField(required=False, allow_blank=False, max_length=256)
class BookingsStatistics(APIView):
permission_classes = (permissions.IsAuthenticated,)
serializer_class = serializers.StatisticsFiltersSerializer
def get(self, request, *args, **kwargs):
serializer = StatisticsFiltersSerializer(data=request.query_params)
serializer = self.serializer_class(data=request.query_params)
if not serializer.is_valid():
raise APIError(
_('invalid statistics filters'),