api: use rest_framework serializers (#22979)

This commit is contained in:
Thomas NOËL 2018-04-04 16:07:00 +02:00
parent 385670124f
commit 87f8cbff15
2 changed files with 58 additions and 26 deletions

View File

@ -25,8 +25,7 @@ from django.shortcuts import get_object_or_404
from django.utils.dateparse import parse_date
from django.utils.timezone import now, make_aware, localtime
from rest_framework import permissions, serializers
from rest_framework.generics import GenericAPIView
from rest_framework import permissions, serializers, status
from rest_framework.response import Response
from rest_framework.views import APIView
@ -116,7 +115,7 @@ def get_agenda_detail(request, agenda):
return agenda_detail
class Agendas(GenericAPIView):
class Agendas(APIView):
permission_classes = ()
def get(self, request, format=None):
@ -127,7 +126,7 @@ class Agendas(GenericAPIView):
agendas = Agendas.as_view()
class AgendaDetail(GenericAPIView):
class AgendaDetail(APIView):
'''
Retrieve an agenda instance.
'''
@ -140,7 +139,7 @@ class AgendaDetail(GenericAPIView):
agenda_detail = AgendaDetail.as_view()
class Datetimes(GenericAPIView):
class Datetimes(APIView):
permission_classes = ()
def get(self, request, agenda_identifier=None, format=None):
@ -200,7 +199,7 @@ class Datetimes(GenericAPIView):
datetimes = Datetimes.as_view()
class MeetingDatetimes(GenericAPIView):
class MeetingDatetimes(APIView):
permission_classes = ()
def get(self, request, agenda_identifier=None, meeting_identifier=None, format=None):
@ -252,7 +251,7 @@ class MeetingDatetimes(GenericAPIView):
meeting_datetimes = MeetingDatetimes.as_view()
class MeetingList(GenericAPIView):
class MeetingList(APIView):
permission_classes = ()
def get(self, request, agenda_identifier=None, format=None):
@ -281,7 +280,7 @@ class MeetingList(GenericAPIView):
meeting_list = MeetingList.as_view()
class AgendaDeskList(GenericAPIView):
class AgendaDeskList(APIView):
permission_classes = ()
def get(self, request, agenda_identifier=None, format=None):
@ -299,11 +298,13 @@ agenda_desk_list = AgendaDeskList.as_view()
class SlotSerializer(serializers.Serializer):
pass
label = serializers.CharField(max_length=150, allow_blank=True, required=False)
user_name = serializers.CharField(max_length=250, allow_blank=True, required=False)
backoffice_url = serializers.URLField(allow_blank=True, required=False)
count = serializers.IntegerField(min_value=1, required=False)
class Fillslot(GenericAPIView):
serializer_class = SlotSerializer
class Fillslot(APIView):
permission_classes = (permissions.IsAuthenticated,)
def post(self, request, agenda_identifier=None, event_pk=None, format=None):
@ -316,6 +317,22 @@ class Fillslot(GenericAPIView):
except (ValueError, Agenda.DoesNotExist):
raise Http404()
serializer = SlotSerializer(data=request.data)
if not serializer.is_valid():
return Response({
'err': 1,
'reason': 'invalid payload',
'errors': serializer.errors
}, status=status.HTTP_400_BAD_REQUEST)
label = serializer.validated_data.get('label') or ''
user_name = serializer.validated_data.get('user_name') or ''
backoffice_url = serializer.validated_data.get('backoffice_url') or ''
places_count = serializer.validated_data.get('count') or 1
extra_data = {}
for k, v in request.data.items():
if k not in serializer.validated_data:
extra_data[k] = v
if 'count' in request.GET:
try:
places_count = int(request.GET['count'])
@ -323,9 +340,7 @@ class Fillslot(GenericAPIView):
return Response({
'err': 1,
'reason': 'invalid value for count (%r)' % request.GET['count'],
})
else:
places_count = 1
}, status=status.HTTP_400_BAD_REQUEST)
available_desk = None
if agenda.kind == 'meetings':
@ -358,10 +373,8 @@ class Fillslot(GenericAPIView):
event_pk = event.id
event = Event.objects.filter(id=event_pk)[0]
new_booking = Booking(event_id=event_pk, extra_data=request.data)
for attr in ('label', 'user_name', 'backoffice_url'):
if isinstance(request.data.get(attr), basestring):
setattr(new_booking, attr, request.data.get(attr))
new_booking = Booking(event_id=event_pk, extra_data=extra_data,
label=label, user_name=user_name, backoffice_url=backoffice_url)
if event.waiting_list_places:
if (event.booked_places + places_count) > event.places or event.waiting_list:
@ -378,7 +391,9 @@ class Fillslot(GenericAPIView):
new_booking.save()
for i in range(places_count-1):
additional_booking = Booking(event_id=event_pk, extra_data=request.data)
additional_booking = Booking(event_id=event_pk, extra_data=extra_data,
label=label, user_name=user_name,
backoffice_url=backoffice_url)
additional_booking.in_waiting_list = new_booking.in_waiting_list
additional_booking.primary_booking = new_booking
additional_booking.save()
@ -468,8 +483,7 @@ class AcceptBooking(APIView):
accept_booking = AcceptBooking.as_view()
class SlotStatus(GenericAPIView):
serializer_class = SlotSerializer
class SlotStatus(APIView):
permission_classes = (permissions.IsAuthenticated,)
def get(self, request, agenda_identifier=None, event_pk=None, format=None):

View File

@ -328,15 +328,33 @@ def test_booking_api(app, some_data, user):
# test with additional data
resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
params={'label': 'foo', 'user_name': 'bar', 'backoffice_url': 'http://baz/'})
params={'label': 'foo', 'user_name': 'bar', 'backoffice_url': 'http://example.net/'})
assert Booking.objects.get(id=resp.json['booking_id']).label == 'foo'
assert Booking.objects.get(id=resp.json['booking_id']).user_name == 'bar'
assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == 'http://baz/'
assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == 'http://example.net/'
# test invalid data are silently ignored
# blank data are OK
resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
params={'user_name': {'foo': 'bar'}})
params={'label': '', 'user_name': '', 'backoffice_url': ''})
assert Booking.objects.get(id=resp.json['booking_id']).label == ''
assert Booking.objects.get(id=resp.json['booking_id']).user_name == ''
assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == ''
# extra data stored in extra_data field
resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
params={'label': 'l', 'user_name': 'u', 'backoffice_url': '', 'foo': 'bar'})
assert Booking.objects.get(id=resp.json['booking_id']).label == 'l'
assert Booking.objects.get(id=resp.json['booking_id']).user_name == 'u'
assert Booking.objects.get(id=resp.json['booking_id']).backoffice_url == ''
assert Booking.objects.get(id=resp.json['booking_id']).extra_data == {'foo': 'bar'}
# test invalid data are refused
resp = app.post_json('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id),
params={'user_name': {'foo': 'bar'}}, status=400)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid payload'
assert len(resp.json['errors']) == 1
assert 'user_name' in resp.json['errors']
resp = app.post('/api/agenda/foobar/fillslot/%s/' % event.id, status=404)
@ -666,7 +684,7 @@ def test_multiple_booking_api(app, some_data, user):
event_fillslot_url = [x for x in resp_datetimes.json['data'] if x['id'] == event.id][0]['api']['fillslot_url']
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/?count=NaN' % (agenda.slug, event.id))
resp = app.post('/api/agenda/%s/fillslot/%s/?count=NaN' % (agenda.slug, event.id), status=400)
assert resp.json['err'] == 1
assert resp.json['reason'] == "invalid value for count (u'NaN')"