编写插件¶
你可以编写只应用于一个 Datasette 实例的一次性插件,也可以编写可以使用 pip
安装并发布到 Python 包索引 (PyPI) 供其他人安装的插件。
想从一个例子开始吗?Datasette 插件目录列出了 90 多个开源插件,你可以探索其代码。插件钩子页面包含了每个已文档化钩子的示例插件链接。
编写一次性插件¶
开始编写插件最快的方式是创建一个 my_plugin.py
文件并将其放入你的 plugins/
目录。这里有一个示例插件,它添加了一个新的自定义 SQL 函数,名为 hello_world()
,该函数不接受任何参数并返回字符串 Hello world!
。
from datasette import hookimpl
@hookimpl
def prepare_connection(conn):
conn.create_function(
"hello_world", 0, lambda: "Hello world!"
)
如果你将其保存在 plugins/my_plugin.py
中,你可以这样启动 Datasette
datasette serve mydb.db --plugins-dir=plugins/
现在你可以导航到 http://localhost:8001/mydb 并运行此 SQL
select hello_world();
以查看你的插件输出。
打包插件¶
插件可以使用 Python setuptools 进行打包。你可以在 https://github.com/simonw/datasette-plugin-demos 查看打包插件的示例。
该示例包含两个文件:一个定义插件的 setup.py
文件
from setuptools import setup
VERSION = "0.1"
setup(
name="datasette-plugin-demos",
description="Examples of plugins for Datasette",
author="Simon Willison",
url="https://github.com/simonw/datasette-plugin-demos",
license="Apache License, Version 2.0",
version=VERSION,
py_modules=["datasette_plugin_demos"],
entry_points={
"datasette": [
"plugin_demos = datasette_plugin_demos"
]
},
install_requires=["datasette"],
)
以及一个实现插件的 Python 模块文件 datasette_plugin_demos.py
from datasette import hookimpl
import random
@hookimpl
def prepare_jinja2_environment(env):
env.filters["uppercase"] = lambda u: u.upper()
@hookimpl
def prepare_connection(conn):
conn.create_function(
"random_integer", 2, random.randint
)
以这种方式构建插件后,你可以使用以下命令将其转换为可安装的包
python3 setup.py sdist
这将在 dist/
目录下创建一个 .tar.gz
文件。
然后你可以使用 pip
将你的新插件安装到 Datasette 虚拟环境或 Docker 容器中
pip install datasette-plugin-demos-0.1.tar.gz
静态资源¶
如果你的插件有一个 static/
目录,Datasette 将自动配置自己从以下路径提供这些静态资源
/-/static-plugins/NAME_OF_PLUGIN_PACKAGE/yourfile.js
使用 datasette.urls.static_plugins(plugin_name, path)
方法生成考虑了 base_url
设置的该资源的 URL,详见 datasette.urls。
要在你发布到 PyPI 的包中捆绑插件的静态资源,请将以下内容添加到插件的 setup.py
package_data = (
{
"datasette_plugin_name": [
"static/plugin.js",
],
},
)
其中 datasette_plugin_name
是插件包的名称(注意使用下划线而不是连字符),static/plugin.js
是该包内静态文件的路径。
datasette-cluster-map 是一个有用的示例插件,它以这种方式包含了打包的静态资源。
自定义模板¶
如果你的插件有一个 templates/
目录,Datasette 将会尝试先从该目录加载模板,然后才使用其默认模板。
模板加载的优先级顺序是
来自
--template-dir
参数指定的模板(如果指定)来自任何已安装插件中
templates/
目录的模板Datasette 附带的默认模板
有关如何编写自定义模板的更多详细信息,包括使用哪些文件名来定制 Datasette UI 的哪些部分,请参阅自定义页面和模板。
模板应使用上面为静态资源描述的 setup.py
中的相同 package_data
机制进行捆绑分发,例如
package_data = (
{
"datasette_plugin_name": [
"templates/my_template.html",
],
},
)
你还可以在此处使用通配符,例如 templates/*.html
。有关此模式的示例,请参阅 datasette-edit-schema。
编写接受配置的插件¶
在编写插件时,你可以使用 datasette plugin_config()
方法像这样访问插件配置。如果你知道需要特定表的插件配置,可以这样访问
plugin_config = datasette.plugin_config(
"datasette-cluster-map", database="sf-trees", table="Street_Tree_List"
)
在上面的示例中,这将返回 {"latitude_column": "lat", "longitude_column": "lng"}
。
如果该插件没有配置,该方法将返回 None
。
如果它在表层找不到所需的配置,它将回退到数据库层,然后再回退到根层。例如,用户可能已像这样设置了插件配置选项
{
"databases: {
"sf-trees": {
"plugins": {
"datasette-cluster-map": {
"latitude_column": "xlat",
"longitude_column": "xlng"
}
}
}
}
}
在这种情况下,上面的代码将为 sf-trees
数据库中的任何表返回该配置。
插件配置也可以在 metadata.json
的顶层设置
{
"title": "This is the top-level title in metadata.json",
"plugins": {
"datasette-cluster-map": {
"latitude_column": "xlat",
"longitude_column": "xlng"
}
}
}
现在 datasette-cluster-map
插件配置将应用于每个数据库中的每个表。
为你的插件设计 URL¶
你可以使用 register_routes(datasette) 插件钩子在 Datasette 中注册新的 URL 路由。
Datasette 的默认 URL 包括这些
/dbname
- 数据库页面/dbname/tablename
- 表页面/dbname/tablename/pk
- 行页面
有关更多默认 URL 路由,请参阅页面和 API 端点以及自省。
为避免意外与可能加载到 Datasette 的数据库文件冲突,插件应使用 /-/
前缀注册 URL。例如,如果你的插件添加了一个新的 Excel 文件上传界面,你可能会注册一个像这样的 URL 路由
/-/upload-excel
尽量避免注册与用户可能已安装的其他插件冲突的 URL。目前还没有保留 URL 路径的中央仓库,但你可以通过浏览 插件目录 <https://datasette.com.cn/plugins> 来查看现有插件。
如果你的插件包含与特定数据库相关的功能,你也可以注册一个像这样的 URL 路由
/dbname/-/upload-excel
或者对于特定表,像这样
/dbname/tablename/-/modify-table-schema
请注意,行的主键可能是 -
,并且此 URL 方案仍然有效,因为 Datasette 行页面后面永远不会有斜杠后跟额外的路径组成部分。
在插件内部构建 URL¶
定义自己的自定义用户界面元素的插件可能需要链接到 Datasette 中的其他页面。
如果 Datasette 实例使用 base_url 配置设置在代理后面运行,这可能会有点棘手,因为它可能导致 Datasette 的 URL 包含额外的路径前缀。
datasette.urls
对象提供了内部方法,用于正确生成指向 Datasette 中不同页面的 URL,同时考虑任何 base_url
配置。
此对象在模板中作为 urls
变量公开,可以这样使用
Back to the <a href="{{ urls.instance() }}">Homepage</a>
有关此对象的完整详细信息,请参阅datasette.urls。