adds a schedule json endpoint. based on @taavi's PR #45 with some changes from the @pyohio/pyohio repo
This commit is contained in:
parent
c4db94b7e5
commit
51709c6eaf
6 changed files with 201 additions and 35 deletions
11
requirements-test.txt
Normal file
11
requirements-test.txt
Normal 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
|
62
symposion/schedule/tests/factories.py
Normal file
62
symposion/schedule/tests/factories.py
Normal 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
|
68
symposion/schedule/tests/runtests.py
Executable file
68
symposion/schedule/tests/runtests.py
Executable 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")
|
31
symposion/schedule/tests/test_views.py
Normal file
31
symposion/schedule/tests/test_views.py
Normal 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
|
|
@ -1,9 +1,5 @@
|
|||
# flake8: noqa
|
||||
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",
|
||||
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\-]+)/presentations.csv$", "schedule_list_csv", name="schedule_list_csv"),
|
||||
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"),
|
||||
)
|
||||
|
|
|
@ -1,8 +1,13 @@
|
|||
from datetime import datetime
|
||||
import json
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from django.http import Http404, HttpResponse
|
||||
from django.shortcuts import render, get_object_or_404, redirect
|
||||
from django.template import loader, Context
|
||||
|
||||
from django.contrib.auth.decorators import login_required
|
||||
from django.contrib.sites.models import Site
|
||||
|
||||
from symposion.schedule.forms import SlotEditForm
|
||||
from symposion.schedule.models import Schedule, Day, Slot, Presentation
|
||||
|
@ -159,46 +164,39 @@ def schedule_presentation_detail(request, pk):
|
|||
|
||||
|
||||
def schedule_json(request):
|
||||
everything = bool(request.GET.get('everything'))
|
||||
slots = Slot.objects.all().order_by("start")
|
||||
slots = Slot.objects.filter(day__schedule__published=True, day__schedule__hidden=False).order_by("start")
|
||||
|
||||
protocol = request.META.get('HTTP_X_FORWARDED_PROTO', 'http')
|
||||
data = []
|
||||
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,
|
||||
"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"],
|
||||
"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" % (
|
||||
"content_href": "%s://%s%s" % (
|
||||
protocol,
|
||||
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
|
||||
slot_data.update({
|
||||
"name": slot.content_override.raw if slot.content_override else "Slot",
|
||||
})
|
||||
data.append(slot_data)
|
||||
|
||||
return HttpResponse(
|
||||
|
|
Loading…
Reference in a new issue