api: update datetimes/fillslot API to get agenda by slug (#13792)

This commit is contained in:
Frédéric Péters 2016-10-28 17:52:21 +02:00
parent dc5c647391
commit a233f39dd1
5 changed files with 51 additions and 28 deletions

View File

@ -21,9 +21,9 @@ from . import views
urlpatterns = patterns('',
url(r'agenda/$', views.agendas),
url(r'agenda/(?P<pk>\w+)/datetimes/$', views.datetimes, name='api-agenda-datetimes'),
url(r'agenda/(?P<agenda_pk>\w+)/fillslot/(?P<event_pk>[\w:-]+)/$', views.fillslot),
url(r'agenda/(?P<agenda_pk>\w+)/status/(?P<event_pk>\w+)/$', views.slot_status),
url(r'agenda/(?P<agenda_identifier>[\w-]+)/datetimes/$', views.datetimes, name='api-agenda-datetimes'),
url(r'agenda/(?P<agenda_identifier>[\w-]+)/fillslot/(?P<event_pk>[\w:-]+)/$', views.fillslot),
url(r'agenda/(?P<agenda_identifier>[\w-]+)/status/(?P<event_pk>\w+)/$', views.slot_status),
url(r'agenda/meetings/(?P<pk>\w+)/datetimes/$', views.meeting_datetimes,
name='api-agenda-meeting-datetimes'),

View File

@ -17,6 +17,7 @@
import datetime
from django.core.urlresolvers import reverse
from django.http import Http404
from django.shortcuts import get_object_or_404
from django.utils.timezone import now, make_aware
@ -30,13 +31,14 @@ from ..agendas.models import Agenda, Event, Booking, MeetingType, TimePeriod
class Agendas(GenericAPIView):
def get(self, request, pk=None, format=None):
def get(self, request, agenda_identifier=None, format=None):
response = {'data': [{
'id': x.id,
'slug': x.slug,
'api': {
'datetimes': request.build_absolute_uri(
reverse('api-agenda-datetimes', kwargs={'pk': x.id})),
reverse('api-agenda-datetimes',
kwargs={'agenda_identifier': x.slug})),
},
'text': x.label}
for x in Agenda.objects.all().order_by('label')]}
@ -46,8 +48,15 @@ agendas = Agendas.as_view()
class Datetimes(GenericAPIView):
def get(self, request, pk=None, format=None):
agenda = Agenda.objects.get(id=pk)
def get(self, request, agenda_identifier=None, format=None):
try:
agenda = Agenda.objects.get(slug=agenda_identifier)
except Agenda.DoesNotExist:
try:
# legacy access by agenda id
agenda = Agenda.objects.get(id=int(agenda_identifier))
except ValueError:
raise Http404()
if agenda.kind != 'events':
raise APIException('not an events agenda')
@ -56,7 +65,7 @@ class Datetimes(GenericAPIView):
if agenda.maximal_booking_delay:
kwargs['start_datetime__lt'] = (now() + datetime.timedelta(days=agenda.maximal_booking_delay)).date()
entries = Event.objects.filter(agenda=pk).filter(**kwargs)
entries = Event.objects.filter(agenda=agenda).filter(**kwargs)
response = {'data': [{'id': x.id,
'text': unicode(x),
@ -115,8 +124,16 @@ class Fillslot(GenericAPIView):
serializer_class = SlotSerializer
permission_classes = (permissions.IsAuthenticated,)
def post(self, request, agenda_pk=None, event_pk=None, format=None):
agenda = Agenda.objects.get(id=agenda_pk)
def post(self, request, agenda_identifier=None, event_pk=None, format=None):
try:
agenda = Agenda.objects.get(slug=agenda_identifier)
except Agenda.DoesNotExist:
try:
# legacy access by agenda id
agenda = Agenda.objects.get(id=int(agenda_identifier))
except ValueError:
raise Http404()
if agenda.kind == 'meetings':
# event is actually a timeslot, convert to a real event object
meeting_type_id, start_datetime_str = event_pk.split(':')
@ -220,7 +237,7 @@ class SlotStatus(GenericAPIView):
serializer_class = SlotSerializer
permission_classes = (permissions.IsAuthenticated,)
def get(self, request, agenda_pk=None, event_pk=None, format=None):
def get(self, request, agenda_identifier=None, event_pk=None, format=None):
event = get_object_or_404(Event, id=event_pk)
response = {
'err': 0,

View File

@ -3,7 +3,7 @@
{% block appbar %}
<h2>{{ object.label }}
<span class="identifier">[{% trans "identifier:" %} {{object.id}}]</span></h2>
<span class="identifier">[{% trans "identifier:" %} {{object.slug}}]</span></h2>
</h2>
{% if user.is_staff %}
<a rel="popup" href="{% url 'chrono-manager-agenda-delete' pk=object.id %}">{% trans 'Delete' %}</a>

View File

@ -62,7 +62,7 @@ agenda_add = AgendaAddView.as_view()
class AgendaEditView(UpdateView):
template_name = 'chrono/manager_agenda_form.html'
model = Agenda
fields = ['label', 'edit_role', 'view_role', 'minimal_booking_delay', 'maximal_booking_delay']
fields = ['label', 'slug', 'edit_role', 'view_role', 'minimal_booking_delay', 'maximal_booking_delay']
def get_object(self, queryset=None):
obj = super(AgendaEditView, self).get_object(queryset=queryset)

View File

@ -65,19 +65,18 @@ def meetings_agenda():
return agenda
def test_agendas_api(app, some_data):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
agenda2_id = Agenda.objects.filter(label=u'Foo bar2')[0].id
agenda1 = Agenda.objects.filter(label=u'Foo bar')[0]
agenda2 = Agenda.objects.filter(label=u'Foo bar2')[0]
resp = app.get('/api/agenda/')
assert resp.json == {'data': [
{'text': 'Foo bar', 'id': agenda_id, 'slug': u'foo-bar',
'api': {'datetimes': 'http://localhost:80/api/agenda/%s/datetimes/' % agenda_id}},
{'text': 'Foo bar2', 'id': agenda2_id, 'slug': u'foo-bar2',
'api': {'datetimes': 'http://localhost:80/api/agenda/%s/datetimes/' % agenda2_id}}
{'text': 'Foo bar', 'id': agenda1.id, 'slug': u'foo-bar',
'api': {'datetimes': 'http://localhost:80/api/agenda/%s/datetimes/' % agenda1.slug}},
{'text': 'Foo bar2', 'id': agenda2.id, 'slug': u'foo-bar2',
'api': {'datetimes': 'http://localhost:80/api/agenda/%s/datetimes/' % agenda2.slug}}
]}
def test_datetimes_api(app, some_data):
agenda = Agenda.objects.filter(label=u'Foo bar')[0]
agenda_id = agenda.id
def check_bookability(data):
for event in data:
@ -86,27 +85,30 @@ def test_datetimes_api(app, some_data):
if not event.in_bookable_period():
assert not event.id in [x['id'] for x in data]
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
resp = app.get('/api/agenda/xxx/datetimes/', status=404)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert 'data' in resp.json
assert len(resp.json['data']) == 3
check_bookability(resp.json['data'])
assert app.get('/api/agenda/%s/datetimes/' % agenda.id).json == resp.json
agenda.minimal_booking_delay = 5
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 0
check_bookability(resp.json['data'])
agenda.minimal_booking_delay = 2
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 2
check_bookability(resp.json['data'])
agenda.minimal_booking_delay = 0
agenda.maximal_booking_delay = 3
agenda.save()
resp = app.get('/api/agenda/%s/datetimes/' % agenda_id)
resp = app.get('/api/agenda/%s/datetimes/' % agenda.slug)
assert len(resp.json['data']) == 2
check_bookability(resp.json['data'])
@ -164,17 +166,21 @@ def test_datetimes_api_meetings_agenda(app, meetings_agenda):
assert resp.json['data'][3] == resp2.json['data'][2]
def test_booking_api(app, some_data, user):
agenda_id = Agenda.objects.filter(label=u'Foo bar')[0].id
event = Event.objects.filter(agenda_id=agenda_id)[0]
agenda = Agenda.objects.filter(label=u'Foo bar')[0]
event = Event.objects.filter(agenda=agenda)[0]
# unauthenticated
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id), status=403)
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.id), status=403)
app.authorization = ('Basic', ('john.doe', 'password'))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda_id, event.id))
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.slug, event.id))
Booking.objects.get(id=resp.json['booking_id'])
assert Booking.objects.count() == 1
resp = app.post('/api/agenda/%s/fillslot/%s/' % (agenda.id, event.id))
assert Booking.objects.count() == 2
assert Booking.objects.filter(event__agenda=agenda).count() == 2
def test_booking_api_meeting(app, meetings_agenda, user):
agenda_id = meetings_agenda.id
meeting_type = MeetingType.objects.get(agenda=meetings_agenda)