First pass at /opds/{facet} --> now with active_campaigns too

pull/1/head
Raymond Yee 2014-06-25 18:05:57 -07:00
parent 8830919318
commit b356699c9b
4 changed files with 92 additions and 24 deletions

View File

@ -32,7 +32,9 @@ def map_to_domain(url, domain="unglue.it", protocol="https"):
return urlparse.urlunparse(m) return urlparse.urlunparse(m)
def add_query_component(url, qc): def add_query_component(url, qc):
""" """ """
add component qc to the querystring of url
"""
m = list(urlparse.urlparse(url)) m = list(urlparse.urlparse(url))
if len(m[4]): if len(m[4]):
m[4] = "&".join([m[4],qc]) m[4] = "&".join([m[4],qc])
@ -107,7 +109,26 @@ def work_node(work, domain="unglue.it", protocol="https"):
return node return node
def creativecommons(domain="unglue.it", protocol="https"): def creative_commons(domain="unglue.it", protocol="https"):
licenses = cc.LICENSE_LIST
ccworks = models.Work.objects.filter(editions__ebooks__isnull=False,
editions__ebooks__rights__in=licenses).distinct().order_by('-created')
return opds_feed_for_works(ccworks, "creative_commons", "Unglue.it Catalog: Creative Commons Books",
domain, protocol)
def active_campaigns(domain="unglue.it", protocol="https"):
"""
return opds feed for works associated with active campaigns
"""
# campaigns = models.Campaign.objects.filter(status='ACTIVE').order_by('deadline')
campaign_works = models.Work.objects.filter(campaigns__status='ACTIVE')
return opds_feed_for_works(campaign_works, "active_campaigns",
"Unglue.it Catalog: Books under Active Campaign",
domain, protocol)
def opds_feed_for_works(works, feed_path, title="Unglue.it Catalog", domain="unglue.it", protocol="https"):
feed_xml = """<feed xmlns:dcterms="http://purl.org/dc/terms/" feed_xml = """<feed xmlns:dcterms="http://purl.org/dc/terms/"
xmlns:opds="http://opds-spec.org/" xmlns:opds="http://opds-spec.org/"
@ -121,12 +142,13 @@ def creativecommons(domain="unglue.it", protocol="https"):
# add title # add title
# TO DO: will need to calculate the number items and where in the feed we are # TO DO: will need to calculate the number items and where in the feed we are
feed.append(text_node('title', "Unglue.it Catalog: crawlable feed")) feed.append(text_node('title', title))
# id # id
feed.append(text_node('id', "{protocol}://{domain}/opds/creativecommons.xml".format(protocol=protocol, feed.append(text_node('id', "{protocol}://{domain}/opds/{feed_path}".format(protocol=protocol,
domain=domain))) domain=domain,
feed_path=feed_path)))
# updated # updated
# TO DO: fix time zone? # TO DO: fix time zone?
@ -154,12 +176,8 @@ def creativecommons(domain="unglue.it", protocol="https"):
}) })
feed.append(start_link) feed.append(start_link)
licenses = cc.LICENSE_LIST
ccworks = models.Work.objects.filter(editions__ebooks__isnull=False, for work in islice(works,None):
editions__ebooks__rights__in=licenses).distinct().order_by('-created')
for work in islice(ccworks,None):
node = work_node(work, domain=domain, protocol=protocol) node = work_node(work, domain=domain, protocol=protocol)
feed.append(node) feed.append(node)

View File

@ -156,7 +156,7 @@ urlpatterns = patterns(
url(r"^marc/concatenate/$", "marc_concatenate", name="marc_concatenate"), url(r"^marc/concatenate/$", "marc_concatenate", name="marc_concatenate"),
url(r"^accounts/edit/marc_config/$", login_required(MARCConfigView.as_view()), name="marc_config"), url(r"^accounts/edit/marc_config/$", login_required(MARCConfigView.as_view()), name="marc_config"),
url(r"^opds/$", OPDSNavigationView.as_view(template_name="opds.xml"), name="opds"), url(r"^opds/$", OPDSNavigationView.as_view(template_name="opds.xml"), name="opds"),
url(r"^opds/creativecommons.xml/$", OPDSAcquisitionView.as_view(), name="opds_cc") url(r"^opds/(?P<facet>[^/]+)/$", OPDSAcquisitionView.as_view(), name="opds_acqusition")
) )
if settings.DEBUG: if settings.DEBUG:

View File

@ -3195,5 +3195,16 @@ class OPDSAcquisitionView(View):
else: else:
protocol = "https" protocol = "https"
return HttpResponse(opds.creativecommons(domain=site.domain, protocol=protocol), logger.info("request.path: {0}".format(request.path))
logger.info("facet: {0}".format(kwargs.get('facet')))
facet = kwargs.get('facet')
if facet == 'creative_commons':
return HttpResponse(opds.creative_commons(domain=site.domain, protocol=protocol),
content_type="application/atom+xml;profile=opds-catalog;kind=acquisition") content_type="application/atom+xml;profile=opds-catalog;kind=acquisition")
elif facet == 'active_campaigns':
return HttpResponse(opds.active_campaigns(domain=site.domain, protocol=protocol),
content_type="application/atom+xml;profile=opds-catalog;kind=acquisition")
else:
return HttpResponseNotFound("invalid facet")

View File

@ -1,7 +1,7 @@
{ {
"metadata": { "metadata": {
"name": "", "name": "",
"signature": "sha256:6bd6c988240f3f5084034a9aca36b1e1f5de3799a7b1a46c9624e8de724010f2" "signature": "sha256:9c22749755ac63be304b4d1975df24fa2f5ae6afb32dd56374a060df17645c96"
}, },
"nbformat": 3, "nbformat": 3,
"nbformat_minor": 0, "nbformat_minor": 0,
@ -657,16 +657,6 @@
"Tacking on a query component to a URL" "Tacking on a query component to a URL"
] ]
}, },
{
"cell_type": "code",
"collapsed": false,
"input": [
"urlli"
],
"language": "python",
"metadata": {},
"outputs": []
},
{ {
"cell_type": "code", "cell_type": "code",
"collapsed": false, "collapsed": false,
@ -697,6 +687,55 @@
], ],
"prompt_number": 30 "prompt_number": 30
}, },
{
"cell_type": "heading",
"level": 1,
"metadata": {},
"source": [
"Getting works of active campaigns "
]
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"campaigns = models.Campaign.objects.filter(status='ACTIVE').order_by('deadline')\n",
"campaigns"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 32,
"text": [
"[<Campaign: Campaign for Lagos__2060>, <Campaign: Campaign for Dave on Earth>, <Campaign: Campaign for Green Comet>, <Campaign: Campaign for 23rd Century Romance>, <Campaign: Campaign for Moebius Noodles>, <Campaign: Campaign for The Digital Public Domain: Foundations for an Open Culture>, <Campaign: Campaign for The Classic Short Story, 1870-1925: Theory of a Genre>, <Campaign: Campaign for Acts of the Apostles>, <Campaign: Campaign for The Pains>, <Campaign: Campaign for Cheap Complex Devices>, <Campaign: Campaign for Biodigital>, <Campaign: Campaign for Contact With Shadow>]"
]
}
],
"prompt_number": 32
},
{
"cell_type": "code",
"collapsed": false,
"input": [
"models.Work.objects.filter(campaigns__status='ACTIVE')"
],
"language": "python",
"metadata": {},
"outputs": [
{
"metadata": {},
"output_type": "pyout",
"prompt_number": 34,
"text": [
"[<Work: 23rd Century Romance>, <Work: Acts of the Apostles>, <Work: Biodigital>, <Work: Cheap Complex Devices>, <Work: Contact With Shadow>, <Work: Dave on Earth>, <Work: Green Comet>, <Work: Lagos__2060>, <Work: Moebius Noodles>, <Work: The Classic Short Story, 1870-1925: Theory of a Genre>, <Work: The Digital Public Domain: Foundations for an Open Culture>, <Work: The Pains>]"
]
}
],
"prompt_number": 34
},
{ {
"cell_type": "heading", "cell_type": "heading",
"level": 1, "level": 1,