Skip to content

Commit

Permalink
WIP table_filter plugin hook
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Aug 5, 2018
1 parent 4ac9132 commit 5116c4e
Show file tree
Hide file tree
Showing 4 changed files with 48 additions and 5 deletions.
5 changes: 5 additions & 0 deletions datasette/hookspecs.py
Expand Up @@ -33,3 +33,8 @@ def publish_subcommand(publish):
@hookspec(firstresult=True)
def render_cell(value):
"Customize rendering of HTML table cell values"


@hookspec
def table_filter():
"Custom filtering of the current table based on the request"
6 changes: 5 additions & 1 deletion datasette/utils.py
@@ -1,5 +1,5 @@
from contextlib import contextmanager
from collections import OrderedDict
from collections import OrderedDict, namedtuple
import base64
import click
import hashlib
Expand Down Expand Up @@ -39,6 +39,10 @@
ENV SQLITE_EXTENSIONS /usr/lib/x86_64-linux-gnu/mod_spatialite.so
'''

TableFilter = namedtuple("TableFilter", (
"human_description_extras", "where_clauses", "params")
)


class InterruptedError(Exception):
pass
Expand Down
17 changes: 13 additions & 4 deletions datasette/views/table.py
Expand Up @@ -313,7 +313,7 @@ async def data(self, request, name, hash, table, default_labels=False, _next=No
search_args = dict(
pair for pair in special_args.items() if pair[0].startswith("_search")
)
search_descriptions = []
human_description_extras = []
search = ""
if fts_table and search_args:
if "_search" in search_args:
Expand All @@ -324,7 +324,7 @@ async def data(self, request, name, hash, table, default_labels=False, _next=No
fts_table=escape_sqlite(fts_table),
)
)
search_descriptions.append('search matches "{}"'.format(search))
human_description_extras.append('search matches "{}"'.format(search))
params["search"] = search
else:
# More complex: search against specific columns
Expand All @@ -341,13 +341,22 @@ async def data(self, request, name, hash, table, default_labels=False, _next=No
i=i
)
)
search_descriptions.append(
human_description_extras.append(
'search column "{}" matches "{}"'.format(
search_col, search_text
)
)
params["search_{}".format(i)] = search_text

# filter_arguments plugin hook support
for awaitable_fn in pm.hook.table_filter():
extras = await awaitable_fn(
view=self, name=name, table=table, request=request
)
human_description_extras.extend(extras.human_description_extras)
where_clauses.extend(extras.where_clauses)
params.update(extras.params)

table_rows_count = None
sortable_columns = set()
if not is_view:
Expand Down Expand Up @@ -713,7 +722,7 @@ async def data(self, request, name, hash, table, default_labels=False, _next=No
pass

# human_description_en combines filters AND search, if provided
human_description_en = filters.human_description_en(extra=search_descriptions)
human_description_en = filters.human_description_en(extra=human_description_extras)

if sort or sort_desc:
sorted_by = "sorted by {}{}".format(
Expand Down
25 changes: 25 additions & 0 deletions docs/plugins.rst
Expand Up @@ -320,3 +320,28 @@ If the value matches that pattern, the plugin returns an HTML link element:
href=jinja2.escape(data["href"]),
label=jinja2.escape(data["label"] or "") or " "
))
table_filter
~~~~~~~~~~~~

Apply additional SQL filters to the current table based on the request.

This should return an awaitable function with the following signature:

.. code-block:: python
from datasette.utils import TableFilter
@hookimpl
def table_filter():
async def inner(view, name, table, request):
extra_human_descriptions = []
where_clauses = []
params = {}
# ... build those things here
return TableFilter(
human_description_extras=extra_human_descriptions,
where_clauses=where_clauses,
params=params,
)
return inner

0 comments on commit 5116c4e

Please sign in to comment.