Skip to content

Commit

Permalink
[2209] Changed package read to allow for different representations (r…
Browse files Browse the repository at this point in the history
…df/n3)
  • Loading branch information
rossjones committed Mar 15, 2012
1 parent 8825f00 commit 6d303c1
Show file tree
Hide file tree
Showing 4 changed files with 70 additions and 23 deletions.
1 change: 1 addition & 0 deletions ckan/config/routing.py
Expand Up @@ -184,6 +184,7 @@ def make_map():
'history_ajax',
]))
)
m.connect('/dataset/{id}.{format}', action='read')
m.connect('/dataset/{id}', action='read')
m.connect('/dataset/{id}/resource/{resource_id}', action='resource_read')

Expand Down
66 changes: 43 additions & 23 deletions ckan/controllers/package.py
Expand Up @@ -44,7 +44,7 @@ def search_url(params):

class PackageController(BaseController):

def _package_form(self, package_type=None):
def _package_form(self, package_type=None):
return lookup_package_plugin(package_type).package_form()

def _form_to_db_schema(self, package_type=None):
Expand Down Expand Up @@ -83,21 +83,21 @@ def search(self):

# most search operations should reset the page counter:
params_nopage = [(k, v) for k,v in request.params.items() if k != 'page']

def drill_down_url(**by):
params = list(params_nopage)
params.extend(by.items())
return search_url(set(params))
c.drill_down_url = drill_down_url

c.drill_down_url = drill_down_url

def remove_field(key, value):
params = list(params_nopage)
params.remove((key, value))
return search_url(params)

c.remove_field = remove_field

def pager_url(q=None, page=None):
params = list(params_nopage)
params.append(('page', page))
Expand Down Expand Up @@ -144,11 +144,28 @@ def pager_url(q=None, page=None):
c.query_error = True
c.facets = {}
c.page = h.Page(collection=[])

return render('package/search.html')

return render('package/search.html')

def read(self, id):
def _content_type_for_format(self, fmt):
"""
Given a requested format this method determines the content-type
to set and the genshi template loader to use in order to render
it accurately. TextTemplate must be used for non-xml templates
whilst all that are some sort of XML should use MarkupTemplate.
"""
from genshi.template import MarkupTemplate, TextTemplate
types = {
"html": ("text/html; charset=utf-8", MarkupTemplate),
"rdf" : ("application/rdf+xml; charset=utf-8", MarkupTemplate),
"n3" : ("text/plain; charset=utf-8", TextTemplate),
}
if fmt in types:
return types[fmt][0], fmt, types[fmt][1]
return (types["html"][0]), "html", (types["html"][1])


def read(self, id, format='html'):
package_type = self._get_package_type(id.split('@')[0])
context = {'model': model, 'session': model.Session,
'user': c.user or c.author, 'extras_as_string': True,
Expand All @@ -171,7 +188,7 @@ def read(self, id):
abort(400, _('Invalid revision format: %r') % e.args)
elif len(split) > 2:
abort(400, _('Invalid revision format: %r') % 'Too many "@" symbols')

#check if package exists
try:
c.pkg_dict = get_action('package_show')(context, data_dict)
Expand All @@ -181,7 +198,7 @@ def read(self, id):
abort(404, _('Dataset not found'))
except NotAuthorized:
abort(401, _('Unauthorized to read package %s') % id)

#set a cookie so we know whether to display the welcome message
c.hide_welcome_message = bool(request.cookies.get('hide_welcome_message', False))
response.set_cookie('hide_welcome_message', '1', max_age=3600) #(make cross-site?)
Expand All @@ -199,13 +216,16 @@ def read(self, id):
if config.get('rdf_packages'):
accept_header = request.headers.get('Accept', '*/*')
for content_type, exts in negotiate(autoneg_cfg, accept_header):
if "html" not in exts:
if "html" not in exts:
rdf_url = '%s%s.%s' % (config['rdf_packages'], c.pkg.id, exts[0])
redirect(rdf_url, code=303)
break

ctype,extension,loader = self._content_type_for_format(format)
response.headers['Content-Type'] = ctype

PackageSaver().render_package(c.pkg_dict, context)
return render('package/read.html')
return render('package/read.' + extension, loader_class=loader)

def comments(self, id):
package_type = self._get_package_type(id)
Expand Down Expand Up @@ -300,11 +320,11 @@ def history(self, id):
return render('package/history.html')

def new(self, data=None, errors=None, error_summary=None):

package_type = request.path.strip('/').split('/')[0]
if package_type == 'group':
package_type = None

context = {'model': model, 'session': model.Session,
'user': c.user or c.author, 'extras_as_string': True,
'save': 'save' in request.params,}
Expand All @@ -321,7 +341,7 @@ def new(self, data=None, errors=None, error_summary=None):

data = data or clean_dict(unflatten(tuplize_dict(parse_params(
request.params, ignore_keys=[CACHE_PARAMETER]))))
c.pkg_json = json.dumps(data)
c.pkg_json = json.dumps(data)

errors = errors or {}
error_summary = error_summary or {}
Expand Down Expand Up @@ -438,22 +458,22 @@ def history_ajax(self, id):
current_approved, approved = True, True
else:
current_approved = False

data.append({'revision_id': revision['id'],
'message': revision['message'],
'timestamp': revision['timestamp'],
'author': revision['author'],
'approved': bool(revision['approved_timestamp']),
'current_approved': current_approved})

response.headers['Content-Type'] = 'application/json;charset=utf-8'
return json.dumps(data)

def _get_package_type(self, id):
"""
Given the id of a package it determines the plugin to load
Given the id of a package it determines the plugin to load
based on the package's type name (type). The plugin found
will be returned, or None if there is no plugin associated with
will be returned, or None if there is no plugin associated with
the type.
Uses a minimal context to do so. The main use of this method
Expand Down Expand Up @@ -538,8 +558,8 @@ def _form_save_redirect(self, pkgname, action):
url = url.replace('<NAME>', pkgname)
else:
url = h.url_for(controller='package', action='read', id=pkgname)
redirect(url)
redirect(url)

def _adjust_license_id_options(self, pkg, fs):
options = fs.license_id.render_opts['options']
is_included = False
Expand Down Expand Up @@ -574,7 +594,7 @@ def authz(self, id):
def autocomplete(self):
# DEPRECATED in favour of /api/2/util/dataset/autocomplete
q = unicode(request.params.get('q', ''))
if not len(q):
if not len(q):
return ''

context = {'model': model, 'session': model.Session,
Expand Down
1 change: 1 addition & 0 deletions ckan/templates/package/read.n3
@@ -0,0 +1 @@
test
25 changes: 25 additions & 0 deletions ckan/templates/package/read.rdf
@@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<rdf:RDF
xmlns:py="http://genshi.edgewall.org/"
xmlns:owl="http://www.w3.org/2002/07/owl#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:dcat="http://www.w3.org/ns/dcat#"
xmlns:dct="http://purl.org/dc/terms/"
xmlns:rdfs="http://www.w3.org/2000/01/rdf-schema#"
>
<dcat:Dataset rdf:about="${ g.site_url + h.url_for(controller='package',action='read',id=c.pkg_dict['name'])}">
<rdfs:label>${c.pkg_dict['name']}</rdfs:label>
<owl:sameAs rdf:resource="urn:uuid:${c.pkg_dict['id']}"/>
<dct:identifier>${c.pkg_dict['name']}</dct:identifier>
<dct:title>${c.pkg_dict['title']}</dct:title>
<dct:description>${c.pkg_dict['notes']}</dct:description>
<dct:rights rdf:resource="http://purl.org/okfn/licenses/"/>
<dcat:distribution py:if="c.pkg_dict.get('resources',None)">
<py:for each="rsc_dict in c.pkg_dict['resources']">
<dcat:Distribution rdf:nodeID="${ rsc_dict['id'] }">
<dcat:accessURL rdf:resource="${ rsc_dict['url'] }"/>
</dcat:Distribution>
</py:for>
</dcat:distribution>
</dcat:Dataset>
</rdf:RDF>

0 comments on commit 6d303c1

Please sign in to comment.