adds a schedule json endpoint. based on @taavi's PR #45 with some changes from the @pyohio/pyohio repo

This commit is contained in:
Sheila Miguez 2014-09-20 20:20:04 -05:00
parent c4db94b7e5
commit 51709c6eaf
6 changed files with 201 additions and 35 deletions

11
requirements-test.txt Normal file
View file

@ -0,0 +1,11 @@
Django==1.4.15
Pillow==2.5.3
django-discover-runner==1.0
django-markitup==2.2.2
django-model-utils==1.5.0
django-nose==1.2
django-reversion==1.8.0
django-timezones==0.2
factory-boy==2.4.1
nose==1.3.4
pytz==2014.7

View file

@ -0,0 +1,62 @@
import datetime
import random
import factory
from factory import fuzzy
from symposion.schedule.models import Schedule, Day, Slot, SlotKind
from symposion.conference.models import Section, Conference
class ConferenceFactory(factory.DjangoModelFactory):
title = fuzzy.FuzzyText()
start_date = fuzzy.FuzzyDate(datetime.date(2014, 1, 1))
end_date = fuzzy.FuzzyDate(datetime.date(2014, 1, 1) + datetime.timedelta(days=random.randint(1,10)))
#timezone = TimeZoneField("UTC")
class Meta:
model = Conference
class SectionFactory(factory.DjangoModelFactory):
conference = factory.SubFactory(ConferenceFactory)
name = fuzzy.FuzzyText()
slug = fuzzy.FuzzyText()
class Meta:
model = Section
class ScheduleFactory(factory.DjangoModelFactory):
section = factory.SubFactory(SectionFactory)
published = True
hidden = False
class Meta:
model = Schedule
class SlotKindFactory(factory.DjangoModelFactory):
schedule = factory.SubFactory(ScheduleFactory)
label = fuzzy.FuzzyText()
class Meta:
model = SlotKind
class DayFactory(factory.DjangoModelFactory):
schedule = factory.SubFactory(ScheduleFactory)
date = fuzzy.FuzzyDate(datetime.date(2014, 1, 1))
class Meta:
model = Day
class SlotFactory(factory.DjangoModelFactory):
day = factory.SubFactory(DayFactory)
kind = factory.SubFactory(SlotKindFactory)
start = datetime.time(random.randint(0,23), random.randint(0,59))
end = datetime.time(random.randint(0,23), random.randint(0,59))
class Meta:
model = Slot

View file

@ -0,0 +1,68 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
# see runtests.py in https://github.com/pydanny/cookiecutter-djangopackage
import sys
try:
from django.conf import settings
settings.configure(
DEBUG=True,
USE_TZ=True,
DATABASES={
"default": {
"ENGINE": "django.db.backends.sqlite3",
}
},
ROOT_URLCONF="symposion.schedule.urls",
INSTALLED_APPS=[
"django.contrib.auth",
"django.contrib.contenttypes",
"django.contrib.sites",
"markitup",
"reversion",
"symposion",
"symposion.conference",
"symposion.speakers",
"symposion.schedule",
"symposion.proposals",
],
SITE_ID=1,
NOSE_ARGS=['-s'],
MARKITUP_FILTER=('django.contrib.markup.templatetags.markup.textile', {}),
)
try:
import django
setup = django.setup
except AttributeError:
pass
else:
setup()
from django_nose import NoseTestSuiteRunner
except ImportError:
raise ImportError("To fix this error, run: pip install -r requirements-test.txt")
def run_tests(*test_args):
if not test_args:
test_args = ['tests']
# Run tests
test_runner = NoseTestSuiteRunner(verbosity=1)
failures = test_runner.run_tests(test_args)
if failures:
sys.exit(failures)
if __name__ == '__main__':
run_tests("symposion.schedule.tests.test_views")

View file

@ -0,0 +1,31 @@
import json
from django.test.client import Client
from django.test import TestCase
from . import factories
class ScheduleViewTests(TestCase):
def test_empty_json(self):
c = Client()
r = c.get('/conference.json')
assert r.status_code == 200
conference = json.loads(r.content)
assert 'schedule' in conference
assert len(conference['schedule']) == 0
def test_populated_empty_presentations(self):
factories.SlotFactory.create_batch(size=5)
c = Client()
r = c.get('/conference.json')
assert r.status_code == 200
conference = json.loads(r.content)
assert 'schedule' in conference
assert len(conference['schedule']) == 5

View file

@ -1,9 +1,5 @@
# 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",
url(r"^$", "schedule_conference", name="schedule_conference"), url(r"^$", "schedule_conference", name="schedule_conference"),
@ -16,5 +12,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"), url(r"^conference.json", "schedule_json", name="schedule_json"),
) )

View file

@ -1,8 +1,13 @@
from datetime import datetime
import json
from django.core.urlresolvers import reverse
from django.http import Http404, HttpResponse from django.http import Http404, HttpResponse
from django.shortcuts import render, get_object_or_404, redirect from django.shortcuts import render, get_object_or_404, redirect
from django.template import loader, Context from django.template import loader, Context
from django.contrib.auth.decorators import login_required from django.contrib.auth.decorators import login_required
from django.contrib.sites.models import Site
from symposion.schedule.forms import SlotEditForm from symposion.schedule.forms import SlotEditForm
from symposion.schedule.models import Schedule, Day, Slot, Presentation from symposion.schedule.models import Schedule, Day, Slot, Presentation
@ -159,46 +164,39 @@ def schedule_presentation_detail(request, pk):
def schedule_json(request): def schedule_json(request):
everything = bool(request.GET.get('everything')) slots = Slot.objects.filter(day__schedule__published=True, day__schedule__hidden=False).order_by("start")
slots = Slot.objects.all().order_by("start")
protocol = request.META.get('HTTP_X_FORWARDED_PROTO', 'http')
data = [] data = []
for slot in slots: for slot in slots:
if slot.content: slot_data = {
slot_data = { "room": ", ".join(room["name"] for room in slot.rooms.values()),
"rooms": [room["name"] for room in slot.rooms.values()],
"start": datetime.combine(slot.day.date, slot.start).isoformat(),
"end": datetime.combine(slot.day.date, slot.end).isoformat(),
"duration": slot.length_in_minutes,
"kind": slot.kind.label,
"section": slot.day.schedule.section.slug,
}
if hasattr(slot.content, "proposal"):
slot_data.update({
"name": slot.content.title, "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()], "authors": [s.name for s in slot.content.speakers()],
"released": slot.content.proposal.recording_release, "contact": [
# You may wish to change this... s.email for s in slot.content.speakers()
"license": "All Rights Reserved", ] if request.user.is_staff else ["redacted"],
"contact":
[s.email for s in slot.content.speakers()]
if request.user.is_staff
else ["redacted"],
"abstract": slot.content.abstract.raw, "abstract": slot.content.abstract.raw,
"description": slot.content.description.raw, "description": slot.content.description.raw,
"conf_key": slot.content.pk, "content_href": "%s://%s%s" % (
"conf_url": "https://%s%s" % ( protocol,
Site.objects.get_current().domain, Site.objects.get_current().domain,
reverse("schedule_presentation_detail", args=[slot.content.pk]) 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: else:
continue slot_data.update({
"name": slot.content_override.raw if slot.content_override else "Slot",
})
data.append(slot_data) data.append(slot_data)
return HttpResponse( return HttpResponse(