Согласно моему последнему обновлению, кажется, что лучший способ достичь этого - через IPackageController из расширения и использовать before_search()
для изменения параметров поиска.
Это хорошо работает, однако, было бы неплохо, если бы CKAN позволил передавать дополнительные фильтры fq
на свои основные страницы поиска (набор данных и организация ?fq=num_resources:[1 TO *]
и добавлять к fq).Кроме того, кажется, что наборы данных немного отличаются в назначении параметров для fq
, чем в организациях.Вы можете увидеть это в этих 2 строках по их действиям ( поиск в наборе данных против организация прочитана ).В моем случае я решил обработать это только для поиска в наборе данных.
Основные элементы
# In plugin class implement IPackageController.
class CustomPlugin(plugins.SingletonPlugin, toolkit.DefaultDatasetForm):
...
plugins.implements(plugins.IPackageController)
# Lower in plugin class add needed functions from IPackageController,
# I decided to add them all and leave them untouched to avoid various
# errors I was getting.
def before_search(self, search_params):
u'''Extensions will receive a dictionary with the query parameters,
and should return a modified (or not) version of it.
Basically go over all search_params and look for values that contain my
additional filter and remove the double quotes. All fq values are a
single string, so do exact match to not remove other escaping / quotes.
In query string in URL if you do `?num_resources=0` you get datasets with no
resources (the opposite of this query string).
'''
for (param, value) in search_params.items():
if param == 'fq' and 'num_resources:"[' in value:
v = value.replace('num_resources:"[1 TO *]"', 'num_resources:[1 TO *]')
search_params[param] = v
return search_params
def after_search(self, search_results, search_params):
return search_results
def before_index(self, pkg_dict):
return pkg_dict
def before_view(self, pkg_dict):
return pkg_dict
def read(self, entity):
return entity
def create(self, entity):
return entity
def edit(self, entity):
return entity
def delete(self, entity):
return entity
def after_create(self, context, pkg_dict):
return pkg_dict
def after_update(self, context, pkg_dict):
return pkg_dict
def after_delete(self, context, pkg_dict):
return pkg_dict
def after_show(self, context, pkg_dict):
return pkg_dict
Затем для пользовательского интерфейса я добавил пользовательский список фасетов в search.html
template.
<div>
<section class="module module-narrow module-shallow">
{% block facet_list_heading %}
<h2 class="module-heading">
<i class="fa fa-filter"></i>
{% set title = 'Resources (data)' %}
{{ title }}
</h2>
{% endblock %}
{% block facet_list_items %}
{% set title = 'Has Resources (data)' %}
<nav>
<ul class="{{ nav_class or 'list-unstyled nav nav-simple nav-facet' }}">
{% set href = h.remove_url_param('num_resources',
extras=extras,
alternative_url=alternative_url)
if c.fields_grouped['num_resources']
else h.add_url_param(new_params={'num_resources': '[1 TO *]' },
alternative_url=alternative_url) %}
<li class="{{ nav_item_class or 'nav-item' }}{% if c.fields_grouped['num_resources'] %} active{% endif %}">
<a href="{{ href }}" title="{{ title }}">
<span>{{ title }}</span>
</a>
</li>
</ul>
</nav>
{% endblock %}
</section>
</div>
Делая это таким образом, он не добавляет новый фасет с помощью IFacets, так как это добавляет список фасетов для num_resources, который дает опции фильтра 0, 1, 2, 3, ... (или что-то еще, что имеет смысл для вашей установки, например, если набор данных имеет 15 ресурсов, он показывает это как опцию).
Я также сделал некоторые изменения во фрагменте search_form.html
, чтобы получить фильтр фасетов для отображения того, что я хотел, но это было просто лишним.