Adds a schedule_json view which provides a /schedule/conference.json endpoint, of the kind that Carl uses for producing conference videos.
Also useful to feed into mobile schedule apps! It is expected that someone might have to customize this for their own installation (PyCon Canada definitely did, with modifications to some of the models).
This commit is contained in:
parent
a4c4e6953c
commit
c4db94b7e5
3 changed files with 78 additions and 0 deletions
|
@ -1,3 +1,5 @@
|
||||||
|
import datetime
|
||||||
|
|
||||||
from django.core.exceptions import ObjectDoesNotExist
|
from django.core.exceptions import ObjectDoesNotExist
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
|
@ -92,6 +94,29 @@ class Slot(models.Model):
|
||||||
except ObjectDoesNotExist:
|
except ObjectDoesNotExist:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
@property
|
||||||
|
def start_datetime(self):
|
||||||
|
return datetime.datetime(
|
||||||
|
self.day.date.year,
|
||||||
|
self.day.date.month,
|
||||||
|
self.day.date.day,
|
||||||
|
self.start.hour,
|
||||||
|
self.start.minute)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def end_datetime(self):
|
||||||
|
return datetime.datetime(
|
||||||
|
self.day.date.year,
|
||||||
|
self.day.date.month,
|
||||||
|
self.day.date.day,
|
||||||
|
self.end.hour,
|
||||||
|
self.end.minute)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def length_in_minutes(self):
|
||||||
|
return int(
|
||||||
|
(self.end_datetime - self.start_datetime).total_seconds() / 60)
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def rooms(self):
|
def rooms(self):
|
||||||
return Room.objects.filter(pk__in=self.slotroom_set.values("room"))
|
return Room.objects.filter(pk__in=self.slotroom_set.values("room"))
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
# flake8: noqa
|
# flake8: noqa
|
||||||
from django.conf.urls.defaults import url, patterns
|
from django.conf.urls.defaults import url, patterns
|
||||||
|
from django.views.decorators.cache import cache_page
|
||||||
|
|
||||||
|
from symposion.schedule.views import schedule_json
|
||||||
|
|
||||||
|
|
||||||
urlpatterns = patterns("symposion.schedule.views",
|
urlpatterns = patterns("symposion.schedule.views",
|
||||||
|
@ -13,4 +16,5 @@ urlpatterns = patterns("symposion.schedule.views",
|
||||||
url(r"^([\w\-]+)/list/$", "schedule_list", name="schedule_list"),
|
url(r"^([\w\-]+)/list/$", "schedule_list", name="schedule_list"),
|
||||||
url(r"^([\w\-]+)/presentations.csv$", "schedule_list_csv", name="schedule_list_csv"),
|
url(r"^([\w\-]+)/presentations.csv$", "schedule_list_csv", name="schedule_list_csv"),
|
||||||
url(r"^([\w\-]+)/edit/slot/(\d+)/", "schedule_slot_edit", name="schedule_slot_edit"),
|
url(r"^([\w\-]+)/edit/slot/(\d+)/", "schedule_slot_edit", name="schedule_slot_edit"),
|
||||||
|
url(r"^conference.json", cache_page(300)(schedule_json), name="schedule_json"),
|
||||||
)
|
)
|
||||||
|
|
|
@ -156,3 +156,52 @@ def schedule_presentation_detail(request, pk):
|
||||||
"schedule": schedule,
|
"schedule": schedule,
|
||||||
}
|
}
|
||||||
return render(request, "schedule/presentation_detail.html", ctx)
|
return render(request, "schedule/presentation_detail.html", ctx)
|
||||||
|
|
||||||
|
|
||||||
|
def schedule_json(request):
|
||||||
|
everything = bool(request.GET.get('everything'))
|
||||||
|
slots = Slot.objects.all().order_by("start")
|
||||||
|
data = []
|
||||||
|
for slot in slots:
|
||||||
|
if slot.content:
|
||||||
|
slot_data = {
|
||||||
|
"name": slot.content.title,
|
||||||
|
"room": ", ".join(room["name"] for room in slot.rooms.values()),
|
||||||
|
"start": slot.start_datetime.isoformat(),
|
||||||
|
"end": slot.end_datetime.isoformat(),
|
||||||
|
"duration": slot.length_in_minutes,
|
||||||
|
"authors": [s.name for s in slot.content.speakers()],
|
||||||
|
"released": slot.content.proposal.recording_release,
|
||||||
|
# You may wish to change this...
|
||||||
|
"license": "All Rights Reserved",
|
||||||
|
"contact":
|
||||||
|
[s.email for s in slot.content.speakers()]
|
||||||
|
if request.user.is_staff
|
||||||
|
else ["redacted"],
|
||||||
|
"abstract": slot.content.abstract.raw,
|
||||||
|
"description": slot.content.description.raw,
|
||||||
|
"conf_key": slot.content.pk,
|
||||||
|
"conf_url": "https://%s%s" % (
|
||||||
|
Site.objects.get_current().domain,
|
||||||
|
reverse("schedule_presentation_detail", args=[slot.content.pk])
|
||||||
|
),
|
||||||
|
"kind": slot.kind.label,
|
||||||
|
"tags": "",
|
||||||
|
}
|
||||||
|
elif everything:
|
||||||
|
slot_data = {
|
||||||
|
"room": ", ".join(room["name"] for room in slot.rooms.values()),
|
||||||
|
"start": slot.start_datetime.isoformat(),
|
||||||
|
"end": slot.end_datetime.isoformat(),
|
||||||
|
"duration": slot.length_in_minutes,
|
||||||
|
"kind": slot.kind.label,
|
||||||
|
"title": slot.content_override.raw,
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
data.append(slot_data)
|
||||||
|
|
||||||
|
return HttpResponse(
|
||||||
|
json.dumps({'schedule': data}),
|
||||||
|
content_type="application/json"
|
||||||
|
)
|
||||||
|
|
Loading…
Reference in a new issue