api: factorize getting objects from list of slugs (#56104)

This commit is contained in:
Valentin Deniaud 2021-08-11 16:03:09 +02:00
parent fa34281ade
commit 0cf2c62199
4 changed files with 45 additions and 47 deletions

View File

@ -580,7 +580,7 @@ def get_events_from_slots(slots, request, agenda, payload):
try:
events = agenda.event_set.filter(id__in=[int(s) for s in slots]).order_by('start_datetime')
except ValueError:
events = agenda.event_set.filter(slug__in=slots).order_by('start_datetime')
events = get_objects_from_slugs(slots, qs=agenda.event_set).order_by('start_datetime')
for event in events:
if event.start_datetime >= now():
@ -610,16 +610,21 @@ def get_resources_from_request(request, agenda):
if agenda.kind != 'meetings' or 'resources' not in request.GET:
return []
resources_slugs = [s for s in request.GET['resources'].split(',') if s]
resources = list(agenda.resources.filter(slug__in=resources_slugs))
if len(resources) != len(resources_slugs):
unknown_slugs = set(resources_slugs) - {r.slug for r in resources}
unknown_slugs = sorted(list(unknown_slugs))
return list(get_objects_from_slugs(resources_slugs, qs=agenda.resources))
def get_objects_from_slugs(slugs, qs):
slugs = set(slugs)
objects = qs.filter(slug__in=slugs)
if len(objects) != len(slugs):
unknown_slugs = sorted(slugs - {obj.slug for obj in objects})
unknown_slugs = ', '.join(unknown_slugs)
raise APIError(
_('invalid resource: %s') % ', '.join(unknown_slugs),
err_class='invalid resource: %s' % ', '.join(unknown_slugs),
_('invalid slugs: %s' % unknown_slugs),
err_class='invalid slugs: %s' % unknown_slugs,
http_status=status.HTTP_400_BAD_REQUEST,
)
return resources
return objects
def get_start_and_end_datetime_from_request(request):
@ -809,14 +814,7 @@ class MultipleAgendasDatetimes(APIView):
)
agenda_slugs = payload['agendas']
agendas = Agenda.objects.filter(slug__in=agenda_slugs, kind='events')
if len(agendas) != len(set(agenda_slugs)):
not_found_slugs = sorted(set(agenda_slugs) - {agenda.slug for agenda in agendas})
raise APIError(
_('events agendas do not exist: %s') % ', '.join(not_found_slugs),
err_class='events agendas do not exist',
http_status=status.HTTP_404_NOT_FOUND,
)
agendas = get_objects_from_slugs(agenda_slugs, qs=Agenda.objects.filter(kind='events'))
user_external_id = payload.get('user_external_id') or payload.get('exclude_user_external_id')
agendas = Agenda.prefetch_events_and_exceptions(

View File

@ -1441,11 +1441,11 @@ def test_datetimes_multiple_agendas(app):
assert len(resp.json['data']) == 0
# invalid slugs
resp = app.get('/api/agendas/datetimes/', params={'agendas': 'xxx'}, status=404)
assert resp.json['err_desc'] == 'events agendas do not exist: xxx'
resp = app.get('/api/agendas/datetimes/', params={'agendas': 'xxx'}, status=400)
assert resp.json['err_desc'] == 'invalid slugs: xxx'
resp = app.get('/api/agendas/datetimes/', params={'agendas': 'first-agenda,xxx,yyy'}, status=404)
assert resp.json['err_desc'] == 'events agendas do not exist: xxx, yyy'
resp = app.get('/api/agendas/datetimes/', params={'agendas': 'first-agenda,xxx,yyy'}, status=400)
assert resp.json['err_desc'] == 'invalid slugs: xxx, yyy'
# no support for past events
resp = app.get('/api/agendas/datetimes/', params={'agendas': agenda_slugs, 'events': 'past'}, status=400)

View File

@ -385,9 +385,9 @@ def test_booking_api_fillslots(app, some_data, user):
# invalid slots format
resp = app.post_json('/api/agenda/%s/fillslots/' % agenda.id, params={'slots': 'foobar'}, status=400)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'unknown event identifiers or slugs' # legacy
assert resp.json['err_class'] == 'unknown event identifiers or slugs'
assert resp.json['err_desc'] == 'unknown event identifiers or slugs'
assert resp.json['reason'] == 'invalid slugs: foobar' # legacy
assert resp.json['err_class'] == 'invalid slugs: foobar'
assert resp.json['err_desc'] == 'invalid slugs: foobar'
# unknown agendas
resp = app.post('/api/agenda/foobar/fillslots/', status=404)
@ -607,9 +607,9 @@ def test_booking_api_meeting_with_resources(app, user):
status=400,
)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid resource: foobarblah' # legacy
assert resp.json['err_class'] == 'invalid resource: foobarblah'
assert resp.json['err_desc'] == 'invalid resource: foobarblah'
assert resp.json['reason'] == 'invalid slugs: foobarblah' # legacy
assert resp.json['err_class'] == 'invalid slugs: foobarblah'
assert resp.json['err_desc'] == 'invalid slugs: foobarblah'
agenda.resources.remove(resource3)
resp = app.post(
'/api/agenda/%s/fillslot/%s:%s-0900/?resources=%s'
@ -617,27 +617,27 @@ def test_booking_api_meeting_with_resources(app, user):
status=400,
)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid resource: resource-3' # legacy
assert resp.json['err_class'] == 'invalid resource: resource-3'
assert resp.json['err_desc'] == 'invalid resource: resource-3'
assert resp.json['reason'] == 'invalid slugs: resource-3' # legacy
assert resp.json['err_class'] == 'invalid slugs: resource-3'
assert resp.json['err_desc'] == 'invalid slugs: resource-3'
resp = app.post(
'/api/agenda/%s/fillslot/%s:%s-0900/?resources=%s,foobarblah'
% (agenda.pk, meeting_type.pk, tomorrow_str, resource3.slug),
status=400,
)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid resource: foobarblah, resource-3' # legacy
assert resp.json['err_class'] == 'invalid resource: foobarblah, resource-3'
assert resp.json['err_desc'] == 'invalid resource: foobarblah, resource-3'
assert resp.json['reason'] == 'invalid slugs: foobarblah, resource-3' # legacy
assert resp.json['err_class'] == 'invalid slugs: foobarblah, resource-3'
assert resp.json['err_desc'] == 'invalid slugs: foobarblah, resource-3'
resp = app.post(
'/api/agenda/%s/fillslot/%s:%s-0900/?resources=%s,foobarblah'
% (agenda.pk, meeting_type.pk, tomorrow_str, resource1.slug),
status=400,
)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid resource: foobarblah' # legacy
assert resp.json['err_class'] == 'invalid resource: foobarblah'
assert resp.json['err_desc'] == 'invalid resource: foobarblah'
assert resp.json['reason'] == 'invalid slugs: foobarblah' # legacy
assert resp.json['err_class'] == 'invalid slugs: foobarblah'
assert resp.json['err_desc'] == 'invalid slugs: foobarblah'
# booking is canceled: slot is free
booking.cancel()

View File

@ -364,9 +364,9 @@ def test_datetimes_api_meetings_agenda_with_resources(app):
)
resp = app.get(api_url, status=400)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid resource: foobarbaz' # legacy
assert resp.json['err_class'] == 'invalid resource: foobarbaz'
assert resp.json['err_desc'] == 'invalid resource: foobarbaz'
assert resp.json['reason'] == 'invalid slugs: foobarbaz' # legacy
assert resp.json['err_class'] == 'invalid slugs: foobarbaz'
assert resp.json['err_desc'] == 'invalid slugs: foobarbaz'
api_url = '/api/agenda/%s/meetings/%s/datetimes/?resources=%s,foobarbaz' % (
agenda.slug,
meeting_type.slug,
@ -374,15 +374,15 @@ def test_datetimes_api_meetings_agenda_with_resources(app):
)
resp = app.get(api_url, status=400)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid resource: foobarbaz' # legacy
assert resp.json['err_class'] == 'invalid resource: foobarbaz'
assert resp.json['err_desc'] == 'invalid resource: foobarbaz'
assert resp.json['reason'] == 'invalid slugs: foobarbaz' # legacy
assert resp.json['err_class'] == 'invalid slugs: foobarbaz'
assert resp.json['err_desc'] == 'invalid slugs: foobarbaz'
agenda.resources.remove(resource3)
resp = app.get(api_url, status=400)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid resource: foobarbaz, resource-3' # legacy
assert resp.json['err_class'] == 'invalid resource: foobarbaz, resource-3'
assert resp.json['err_desc'] == 'invalid resource: foobarbaz, resource-3'
assert resp.json['reason'] == 'invalid slugs: foobarbaz, resource-3' # legacy
assert resp.json['err_class'] == 'invalid slugs: foobarbaz, resource-3'
assert resp.json['err_desc'] == 'invalid slugs: foobarbaz, resource-3'
api_url = '/api/agenda/%s/meetings/%s/datetimes/?resources=%s' % (
agenda.slug,
meeting_type.slug,
@ -390,9 +390,9 @@ def test_datetimes_api_meetings_agenda_with_resources(app):
)
resp = app.get(api_url, status=400)
assert resp.json['err'] == 1
assert resp.json['reason'] == 'invalid resource: resource-3' # legacy
assert resp.json['err_class'] == 'invalid resource: resource-3'
assert resp.json['err_desc'] == 'invalid resource: resource-3'
assert resp.json['reason'] == 'invalid slugs: resource-3' # legacy
assert resp.json['err_class'] == 'invalid slugs: resource-3'
assert resp.json['err_desc'] == 'invalid slugs: resource-3'
# if booking is canceled the resource is free
booking_r1.cancel()