在 CKAN 中为特定的 REST 请求定制 URL

Making customized URL in CKAN for specific REST request

我想创建一个导出按钮,以便在搜索完成后,导出功能可以将搜索结果导出到 csv 文件中,并将此 csv 文件下载到本地计算机。我有两个想法,但我不知道哪个是CKAN中更好的做法?

  1. 给出一个URL,这样URL将首先接收search_criteria和return json列表的请求,然后转换json 在 csv 中并下载它。在模板文件中,我只需要给出一个URL,比如<a href="{{h.url_for(request url)}}">Export</a>,但我必须在plugin.pycontroller.pyhelpers.py中实现请求句柄。
  2. 提供一个 URL 来处理请求、转换和下载,但在模板文件上,我将 link "Export" 按钮发送到请求 js 文件,例如 <a href="request.js">Export</a> .

对于这两个想法,我必须在路由映射中添加这个新的 url 并在控制器和插件中添加响应、转换和下载。我想知道哪个想法需要更少的修改?

1 对我来说似乎是一个不错的选择 - 您需要使用一些现有的 python 代码,因此 javascript 将是一个更难的选择。

搜索结果由包控制器(来自 CKAN 2.9 的数据集视图)在 search() 方法中生成。它采用查询字符串,对包含搜索参数(例如 SOLR q 和 fq 参数)的 data_dict 进行一些转换。使用这些参数调用 package_search 逻辑函数,并且 return 是 JSON 列表形式的搜索结果列表。现在在呈现模板网页时使用 JSON 的控制器中,但在您的情况下,您希望将其转换为 CSV 和 return。因此,您可以将该控制器 search() 代码(直到渲染)复制并粘贴到您自己的 CKAN 扩展中,将您需要的内容序列化为 CSV,然后 return 它。

或者更好的是你可以做一个供所有人使用的解决方案。在 search() 旁边添加一个控制器方法,并将搜索方法所需的代码分解为它们都调用的单独方法。在模板底部添加 link 并作为 PR 提交。 :)

我选择了第一种方法,效果很好,相比第二种方法,它节省了我为实现export.js

所做的修改

您可以在 url、template/search.html:

中添加任何搜索条件

<a href={{h.url_for("/export", search_criteria='random string', ...)}}></a>

然后在 plugin.py 中你可以覆盖 before_map in IRoutes inferface 并在 before_map 中添加 URL:

class ExportPlugin(plugins.SingletonPlugin):
    plugins.implements(plugins.IRoutes, inherit=True)

    def before_map(self, m):
        m.connect('export', '/export', 
              controller='ckanext.my_export_plugin.controller:ExportController',
              action='export')

然后在 controller.py 中你可以继承 BaseController 这样你就可以通过 package_search API 处理搜索并在 facet 查询中传递任何自定义搜索条件 fq。您还可以在此控制器中添加转换和下载功能:

class ExportController(base.BaseController):

    def json_to_csv(original_json):
        '''
        Other Implementation of convertion
        '''
        return csv.read()

    def export(self, data):
        '''
        Other Implementation of handling search operation
        '''
        search_results = toolkit.get_action('package_search')(data_dict=data)
        file_name = "export.csv"
        response.headers['Content-Type'] = 'application/csv'
        response.headers['Content-Disposition'] = file_name
        return json_to_csv(search_results)

在你自己实现之后,你应该能够为 REST 服务定制 url 并在后端完全处理请求。