Merge pull request #62 from codersquid/json_endpoint

Adds a schedule_json view
This commit is contained in:
Sheila Miguez 2014-09-28 10:45:35 -05:00
commit 0fb224cbf6
7 changed files with 248 additions and 1 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

@ -1,3 +1,5 @@
import datetime
from django.core.exceptions import ObjectDoesNotExist
from django.db import models
@ -92,6 +94,29 @@ class Slot(models.Model):
except ObjectDoesNotExist:
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
def rooms(self):
return Room.objects.filter(pk__in=self.slotroom_set.values("room"))

View file

@ -0,0 +1,63 @@
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,30 @@
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,7 +1,6 @@
# flake8: noqa
from django.conf.urls.defaults import url, patterns
urlpatterns = patterns("symposion.schedule.views",
url(r"^$", "schedule_conference", name="schedule_conference"),
url(r"^edit/$", "schedule_edit", name="schedule_edit"),
@ -13,4 +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", "schedule_json", name="schedule_json"),
)

View file

@ -1,8 +1,12 @@
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
@ -156,3 +160,49 @@ def schedule_presentation_detail(request, pk):
"schedule": schedule,
}
return render(request, "schedule/presentation_detail.html", ctx)
def schedule_json(request):
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:
slot_data = {
"room": ", ".join(room["name"] for room in slot.rooms.values()),
"rooms": [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,
"section": slot.day.schedule.section.slug,
}
if hasattr(slot.content, "proposal"):
slot_data.update({
"name": slot.content.title,
"authors": [s.name for s in slot.content.speakers()],
"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,
"content_href": "%s://%s%s" % (
protocol,
Site.objects.get_current().domain,
reverse("schedule_presentation_detail", args=[slot.content.pk])
),
"cancelled": slot.content.cancelled,
})
else:
slot_data.update({
"name": slot.content_override.raw if slot.content_override else "Slot",
})
data.append(slot_data)
return HttpResponse(
json.dumps({'schedule': data}),
content_type="application/json"
)