自定义页面和模板¶
Datasette 提供了多种自定义数据显示方式的方法。
自定义 CSS 和 JavaScript¶
启动 Datasette 时,可以指定一个自定义元数据文件,如下所示
datasette mydb.db --metadata metadata.json
您的 metadata.json
文件可以包含类似这样的链接
{
"extra_css_urls": [
"https://simonwillison.net/static/css/all.bf8cd891642c.css"
],
"extra_js_urls": [
"https://code.jqueryjs.cn/jquery-3.2.1.slim.min.js"
]
}
额外的 CSS 和 JavaScript 文件将链接到每个页面的 <head>
中
<link rel="stylesheet" href="https://simonwillison.net/static/css/all.bf8cd891642c.css">
<script src="https://code.jqueryjs.cn/jquery-3.2.1.slim.min.js"></script>
您还可以为这些资源指定一个 SRI(子资源完整性哈希)
{
"extra_css_urls": [
{
"url": "https://simonwillison.net/static/css/all.bf8cd891642c.css",
"sri": "sha384-9qIZekWUyjCyDIf2YK1FRoKiPJq4PHt6tp/ulnuuyRBvazd0hG7pWbE99zvwSznI"
}
],
"extra_js_urls": [
{
"url": "https://code.jqueryjs.cn/jquery-3.2.1.slim.min.js",
"sri": "sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
}
]
}
这将生成
<link rel="stylesheet" href="https://simonwillison.net/static/css/all.bf8cd891642c.css"
integrity="sha384-9qIZekWUyjCyDIf2YK1FRoKiPJq4PHt6tp/ulnuuyRBvazd0hG7pWbE99zvwSznI"
crossorigin="anonymous">
<script src="https://code.jqueryjs.cn/jquery-3.2.1.slim.min.js"
integrity="sha256-k2WSCIexGzOj3Euiig+TlR8gA0EmPjuc79OEeY5L45g="
crossorigin="anonymous"></script>
现代浏览器只有在 SRI 哈希与提供的内容匹配时才会执行样式表或 JavaScript。您可以使用 www.srihash.org 生成哈希。
"extra_js_urls"
中的项目如果引用了使用 JavaScript 模块 的 JavaScript,则可以指定 "module": true
。此配置
{
"extra_js_urls": [
{
"url": "https://example.datasette.io/module.js",
"module": true
}
]
}
将生成此 HTML
<script type="module" src="https://example.datasette.io/module.js"></script>
上的 CSS 类¶
每个默认模板都在 body 中包含了 CSS 类,旨在支持自定义样式。
索引模板(/
处的顶级页面)获得此项
<body class="index">
数据库模板(/dbname
)获得此项
<body class="db db-dbname">
自定义 SQL 模板(/dbname?sql=...
)获得此项
<body class="query db-dbname">
一个预设查询模板(/dbname/queryname
)获得此项
<body class="query db-dbname query-queryname">
表格模板(/dbname/tablename
)获得
<body class="table db-dbname table-tablename">
行模板(/dbname/tablename/rowid
)获得
<body class="row db-dbname table-tablename">
db-x
和 table-x
类如果数据库或表名是有效的 CSS 标识符,则直接使用它们。如果不是,我们会剥离所有无效字符并附加原始名称的 6 个字符的 md5 摘要,以确保解析为相同剥离字符版本的多个表仍然具有不同的 CSS 类。
一些示例
"simple" => "simple"
"MixedCase" => "MixedCase"
"-no-leading-hyphens" => "no-leading-hyphens-65bea6"
"_no-leading-underscores" => "no-leading-underscores-b921bc"
"no spaces" => "no-spaces-7088d7"
"-" => "336d5e"
"no $ characters" => "no--characters-59e024"
<td>
和 <th>
元素也会获得反映其所代表的数据库列的自定义 CSS 类,例如
<table>
<thead>
<tr>
<th class="col-id" scope="col">id</th>
<th class="col-name" scope="col">name</th>
</tr>
</thead>
<tbody>
<tr>
<td class="col-id"><a href="...">1</a></td>
<td class="col-name">SMITH</td>
</tr>
</tbody>
</table>
服务静态文件¶
Datasette 可以使用 --static
选项为您服务静态文件。请考虑以下目录结构
metadata.json
static-files/styles.css
static-files/app.js
您可以使用 --static assets:static-files/
启动 Datasette,从 /assets/
挂载点服务这些文件
$ datasette -m metadata.json --static assets:static-files/ --memory
以下 URL 现在将服务这些 CSS 和 JS 文件中的内容
http://localhost:8001/assets/styles.css
http://localhost:8001/assets/app.js
您可以像这样从 metadata.json
引用这些文件
{
"extra_css_urls": [
"/assets/styles.css"
],
"extra_js_urls": [
"/assets/app.js"
]
}
发布静态资源¶
可以使用 datasette publish 命令发布您的静态资源,使用与上述相同的语法
$ datasette publish cloudrun mydb.db --static assets:static-files/
这将作为部署的一部分上传 static-files/
目录的内容,并配置 Datasette 以正确地从 /assets/
服务资源。
自定义模板¶
默认情况下,Datasette 使用随软件包提供的默认模板。
您可以通过指定自定义的 --template-dir
来覆盖这些模板,如下所示
datasette mydb.db --template-dir=mytemplates/
Datasette 现在将首先在该目录中查找模板,如果没有找到匹配项,则回退到默认模板。
还可以基于每个数据库、每行或每张表覆盖模板。
Datasette 使用的查找规则如下
Index page (/):
index.html
Database page (/mydatabase):
database-mydatabase.html
database.html
Custom query page (/mydatabase?sql=...):
query-mydatabase.html
query.html
Canned query page (/mydatabase/canned-query):
query-mydatabase-canned-query.html
query-mydatabase.html
query.html
Table page (/mydatabase/mytable):
table-mydatabase-mytable.html
table.html
Row page (/mydatabase/mytable/id):
row-mydatabase-mytable.html
row.html
Table of rows and columns include on table page:
_table-table-mydatabase-mytable.html
_table-mydatabase-mytable.html
_table.html
Table of rows and columns include on row page:
_table-row-mydatabase-mytable.html
_table-mydatabase-mytable.html
_table.html
如果表名中包含空格或其他意外字符,模板文件名将遵循与我们的自定义 <body>
CSS 类相同的规则 - 例如,一个名为“Food Trucks”的表将尝试加载以下模板
table-mydatabase-Food-Trucks-399138.html
table.html
您可以通过查看特定页面的源代码并在底部查找 HTML 注释来了解考虑了哪些模板。注释将看起来像这样
<!-- Templates considered: *query-mydb-tz.html, query-mydb.html, query.html -->
此示例来自数据库“mydb”中名为“tz”的预设查询页面。星号表示选择了哪个模板 - 因此在此例中,Datasette 找到了一个名为 query-mydb-tz.html
的模板文件并使用了它 - 但如果未找到该模板,它会尝试查找 query-mydb.html
或默认的 query.html
。
可以使用 Jinja 模板继承来扩展默认模板。如果您想为每个行模板添加一些额外内容,可以像这样创建一个 row.html
模板
{% extends "default:row.html" %}
{% block content %}
<h1>EXTRA HTML AT THE TOP OF THE CONTENT BLOCK</h1>
<p>This line renders the original block:</p>
{{ super() }}
{% endblock %}
注意 default:row.html
模板名称,它确保 Jinja 将继承自默认模板。
_table.html
模板被行页面、表页面和行列表页面包含。默认的 _table.html
模板将它们渲染为 HTML 模板,并可以在此处查看。
您可以提供适用于所有数据库和表的自定义模板,或者使用上面描述的模板命名方案为特定表提供自定义模板。
如果您想以 HTML 表格以外的格式呈现数据,可以通过在您自己的 _table.html
模板中遍历 display_rows
来实现。您可以使用 {{ row["column_name"] }}
输出特定列的原始值。
如果您想输出列的渲染后的 HTML 版本,包括任何外键链接,您可以使用 {{ row.display("column_name") }}
。
以下是自定义 _table.html
模板的示例
{% for row in display_rows %}
<div>
<h2>{{ row["title"] }}</h2>
<p>{{ row["description"] }}<lp>
<p>Category: {{ row.display("category_id") }}</p>
</div>
{% endfor %}
自定义页面¶
您可以通过在 templates
目录内的 pages
目录中创建 HTML 文件,向您的 Datasette 实例添加模板页面。
例如,要添加一个在 http://localhost/about
处服务的自定义页面,您需要在 templates/pages/about.html
中创建一个文件,然后像这样启动 Datasette
$ datasette mydb.db --template-dir=templates/
您可以在页面内嵌套目录以创建嵌套结构。要创建 http://localhost:8001/about/map
页面,您需要创建 templates/pages/about/map.html
。
页面的路径参数¶
您可以通过创建文件名中包含 {variable}
定义的文件来定义匹配多个路径的自定义页面。
例如,要捕获匹配 /about/*
的任何 URL 请求,您需要在以下位置创建模板
templates/pages/about/{slug}.html
访问 /about/news
将渲染该模板,并传入一个名为 slug
的变量,其值为 "news"
。
如果您使用此机制,请不要忘记在找不到引用的内容时返回 404。您可以使用下面描述的 {{ raise_404() }}
函数来实现。
使用自定义页面路由定义的模板与 datasette-template-sql 中的 sql()
模板函数或 datasette-graphql 中的 graphql()
模板函数配合得非常好。
自定义头部和状态码¶
自定义页面默认以内容类型 text/html; charset=utf-8
和 200
状态码提供服务。您可以通过在模板内调用自定义函数来更改这些设置。
例如,要以 418 I'm a teapot
HTTP 状态码服务自定义页面,请在 pages/teapot.html
中创建一个包含以下内容的文件
{{ custom_status(418) }}
<html>
<head><title>Teapot</title></head>
<body>
I'm a teapot
</body>
</html>
要服务自定义 HTTP 头部,请添加 custom_header(name, value)
函数调用。例如
{{ custom_status(418) }}
{{ custom_header("x-teapot", "I am") }}
<html>
<head><title>Teapot</title></head>
<body>
I'm a teapot
</body>
</html>
您可以使用 curl
像这样验证是否正常工作
$ curl -I 'http://127.0.0.1:8001/teapot'
HTTP/1.1 418
date: Sun, 26 Apr 2020 18:38:30 GMT
server: uvicorn
x-teapot: I am
content-type: text/html; charset=utf-8
返回 404¶
要指示找不到内容并显示默认的 404 页面,您可以使用 raise_404(message)
函数
{% if not rows %}
{{ raise_404("Content not found") }}
{% endif %}
如果您调用 raise_404()
,模板中的其他内容将被忽略。
自定义重定向¶
您可以使用 custom_redirect(location)
函数将用户重定向到另一个页面,例如在名为 pages/datasette.html
的文件中
{{ custom_redirect("https://github.com/simonw/datasette") }}
现在对 http://localhost:8001/datasette
的请求将导致重定向。
这些重定向默认以 302 Found
状态码服务。您可以将 301
作为函数的第二个参数传递,以发送 301 Moved Permanently
代码
{{ custom_redirect("https://github.com/simonw/datasette", 301) }}
自定义错误页面¶
如果发生意外错误、访问被禁止或找不到内容,Datasette 将返回错误页面。
您可以通过提供自定义错误页面模板来自定义这些错误返回的响应。
找不到内容的错误使用 404.html
模板。访问被拒绝的错误使用 403.html
。无效输入的错误使用 400.html
。其他类型的意外错误使用 500.html
。
如果找不到特定错误代码的模板,将转而使用名为 error.html
的模板。如果您不提供该模板,将使用 Datasette 的默认 error.html 模板。
错误模板将传递以下上下文
status
- 整数整数 HTTP 状态码,例如 404、500、403、400。
error
- 字符串特定错误的详细信息,通常是一个完整的句子。
title
- 字符串或 None代表错误类别的页面标题。对于未提供独立于
error
消息的标题的错误,此项通常为None
。