Skip to content

Commit

Permalink
Fix mozilla#196: Revise awards JSON feed format
Browse files Browse the repository at this point in the history
* Awards JSON feed format now looks more like the OpenBadges Backpack
  Displayer format.

    * JSON object iwth 'badges' property, listing award assertions

* Recent badges JSON feed lists BadgeObjects under 'badges' property

* Test updates
  • Loading branch information
lmorchard committed Jan 24, 2014
1 parent a35925e commit 6fad0a7
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 24 deletions.
34 changes: 13 additions & 21 deletions badger/feeds.py
@@ -1,4 +1,5 @@
"""Feeds for badge"""
import logging
import datetime
import hashlib
import urllib
Expand Down Expand Up @@ -28,34 +29,25 @@
DEFAULT_BADGE_IMAGE)


MAX_FEED_ITEMS = getattr(settings, 'BADGER_MAX_FEED_ITEMS', 15)
MAX_FEED_ITEMS = getattr(settings, 'BADGER_MAX_FEED_ITEMS', 50)


class BaseJSONFeedGenerator(SyndicationFeed):
"""JSON feed generator"""
# TODO:liberate - Can this class be a generally-useful lib?
class OBIJSONFeedGenerator(SyndicationFeed):
"""OBI JSON feed generator"""

serialization_method = 'as_obi_assertion'
mime_type = 'application/json'

def _encode_complex(self, obj):
if isinstance(obj, datetime.datetime):
return obj.isoformat()

def build_item(self, item):
"""Simple base item formatter.
Omit some named keys and any keys with false-y values"""
omit_keys = ('obj', 'unique_id', )
return dict((k, v) for k, v in item.items()
if v and k not in omit_keys)
request = self.feed['request']
return getattr(item['obj'], self.serialization_method)(request)

def build_feed(self):
"""Simple base feed formatter.
Omit some named keys and any keys with false-y values"""
omit_keys = ('obj', 'request', 'id', )
feed_data = dict((k, v) for k, v in self.feed.items()
if v and k not in omit_keys)
feed_data['items'] = [self.build_item(item) for item in self.items]
return feed_data
return dict(badges=[self.build_item(item) for item in self.items])

def write(self, outfile, encoding):
request = self.feed['request']
Expand All @@ -80,7 +72,7 @@ class BaseFeed(Feed):
and other niceties"""
# TODO:liberate - Can this class be a generally-useful lib?

json_feed_generator = BaseJSONFeedGenerator
json_feed_generator = OBIJSONFeedGenerator
rss_feed_generator = Rss201rev2Feed
atom_feed_generator = Atom1Feed

Expand Down Expand Up @@ -136,8 +128,8 @@ def item_description(self, obj):
)


class AwardActivityStreamJSONFeedGenerator(BaseJSONFeedGenerator):
pass
class AwardActivityStreamJSONFeedGenerator(OBIJSONFeedGenerator):
serialization_method = 'as_obi_assertion'


class AwardActivityStreamAtomFeedGenerator(Atom1Feed):
Expand Down Expand Up @@ -216,8 +208,8 @@ def items(self, badge):
.all()[:MAX_FEED_ITEMS])


class BadgesJSONFeedGenerator(BaseJSONFeedGenerator):
pass
class BadgesJSONFeedGenerator(OBIJSONFeedGenerator):
serialization_method = 'as_obi_serialization'


class BadgesFeed(BaseFeed):
Expand Down
73 changes: 70 additions & 3 deletions badger/tests/test_feeds.py
@@ -1,5 +1,6 @@
import logging
import feedparser
import json

from django.conf import settings

Expand Down Expand Up @@ -38,12 +39,13 @@ def tearDown(self):
Award.objects.all().delete()
Badge.objects.all().delete()

def test_award_feeds(self):
"""Can view award detail"""
def test_award_atom_feeds(self):
"""Can view award atom feeds"""
user = self._get_user()
user2 = self._get_user(username='tester2')

b1, created = Badge.objects.get_or_create(creator=user, title="Code Badge #1")
b1, created = Badge.objects.get_or_create(creator=user,
title="Code Badge #1")
award = b1.award_to(user2)

# The award should show up in each of these feeds.
Expand Down Expand Up @@ -72,6 +74,71 @@ def test_award_feeds(self):

ok_(found_it)

def test_badge_json_feeds(self):
user = self._get_user()
user2 = self._get_user(username='tester2')

b1, created = Badge.objects.get_or_create(creator=user,
title="Code Badge #1")

# The award should show up in each of these feeds.
feed_urls = (
reverse('badger.feeds.badges_recent',
args=('json', )),
)

# Check each of the feeds
for feed_url in feed_urls:
r = self.client.get(feed_url, follow=True)

# The feed should be parsed without issues by feedparser
feed = json.loads(r.content)

ok_('badges' in feed)
b1_url = ('http://testserver%s' %
b1.get_absolute_url())
found_it = False
for badge in feed['badges']:
if badge['criteria'] == b1_url:
found_it = True

ok_(found_it)

def test_award_json_feeds(self):
user = self._get_user()
user2 = self._get_user(username='tester2')

b1, created = Badge.objects.get_or_create(creator=user,
title="Code Badge #1")
award = b1.award_to(user2)

# The award should show up in each of these feeds.
feed_urls = (
reverse('badger.feeds.awards_recent',
args=('json', )),
reverse('badger.feeds.awards_by_badge',
args=('json', b1.slug, )),
reverse('badger.feeds.awards_by_user',
args=('json', user2.username,)),
)

# Check each of the feeds
for feed_url in feed_urls:
r = self.client.get(feed_url, follow=True)

# The feed should be parsed without issues by feedparser
feed = json.loads(r.content)

ok_('badges' in feed)
b1_url = ('http://testserver%s' %
b1.get_absolute_url(format='json'))
found_it = False
for badge in feed['badges']:
if badge['badge'] == b1_url:
found_it = True

ok_(found_it)

def _get_user(self, username="tester", email="tester@example.com",
password="trustno1"):
(user, created) = User.objects.get_or_create(username=username,
Expand Down

0 comments on commit 6fad0a7

Please sign in to comment.