Datasette.io,Datasette的官方项目网站

2020-12-24 21:46:58

Datasette的第一个开放源代码发布是在三年前,但是直到现在,官方站点职责仍在GitHub存储库和文档之间进行划分。

该网站本身是基于Datasette构建的(此处为源代码)。我使用的是最初在Niche Museums中探索的模式:大多数网站内容都存储在SQLite数据库中,并且我使用自定义Jinja模板来实现网站的不同页面。

这实际上是静态站点生成器模式的一种变体。 SQLite数据库是在部署过程中由脚本构建的,然后作为与模板和Datasette本身捆绑在一起的二进制资产部署到Google Cloud Run。

我将其称为“烘焙数据”架构模式-感谢Kevin Kevins帮助我创造了正确的术语。您将数据烘焙到应用程序中。

它与静态网站生成具有可比性,因为所有内容都是不可变的,这大大减少了可能出错的地方-并且任何内容更改都需要重新部署。扩展非常容易,只需使用捆绑的数据库副本运行应用程序的更多副本即可。 Cloud Run和其他无服务器提供商会自动处理这种扩展。

与静态网站生成不同,如果一个网站有一千个页面,则无需构建一千个HTML页面即可进行部署。单个模板和包含URL参数的SQL查询可以提供与数据库中的记录一样多的页面。

新闻表会在首页和/ news中提供最新新闻。新闻存放在该站点的GitHub存储库中的news.yaml文件中。我编写了一个脚本来导入在0.52自述文件中累积的新闻-现在新闻已移至该站点,自述文件变得更加苗条!

在构建时,我的yaml-to-sqlite脚本运行以将新闻内容加载到数据库表中。

然后,index.html模板通过使用datasette-template-sql Datasette插件中的sql()函数,使用以下Jinja代码输出最新新闻报道:

{%set ns =名称空间(current_date ="")%} {%用于sql中的行("从日期顺序的新闻顺序中选择日期和正文,以desc限制15"数据库=& #34; content")%} {%如果prettydate(row [" date"])!=(ns。current_date和prettydate(ns。current_date))%}< h3> {{prettydate(row [" date"])}}< a href =" / news / {{row ["日期"]}}"样式="字号:0.8 em;不透明度:0.4" / a< / h3> {%设定ns。 current_date = prettydate(row [" date"])%} {%endif%} {{render_markdown(row [" body"])}} {%endfor%}

prettydate()是我在该网站的一次性插件中编写的自定义函数。 namespace()东西是一个Jinja技巧,它使我可以跟踪循环中的当前日期标题,因此,仅当新闻项与前一天不在同一天时,才可以输出新的日期标题。

我想要新闻报道的永久链接,但是由于它们没有标识符或标题,因此我决定每天提供一个页面,例如https://datasette.io/news/2020-12-10

这些页面是使用Datasette 0.49中引入的自定义页面模板的Path参数实现的。该实现是一个单独的模板文件,位于template / pages / news / {yyyy}-{mm}-{dd} .html,其完整内容为:

{%扩展" page_base.html" %} {%标题%} Datasette News:{{prettydate(yyyy +"-" + mm +"-" + dd)}} {%endblock%} {%块内容%} {%设置故事= sql("从新闻中选择日期,正文,其中date =?按日期顺序排列desc&#34 ;, [yyyy +"-" + mm +&# 34;-" + dd],数据库="内容")%} {%如果没有故事%} {{raise_404(" News not found")}} {% endif%}< h1< a href =" / news" / news / lt; / a&gt ;: {{prettydate(yyyy +"-" + mm +"-" + dd )}}< / h1> {%为故事中的行%} {{render_markdown(row [" body"])}} {%endfor%} {%endblock%}

这里的关键技巧是,因为文件名是news / {yyyy}-{mm}-{dd} .html,所以对/ news / 2020-12-10的请求将使用yyyy,mm和dd模板呈现该模板变量设置为网址中的那些值。

然后,它可以执行包含这些值的SQL查询。它将结果分配给一个故事变量,然后检查是否至少返回了一个故事-如果未返回,则会引发404错误。

有关所有操作的更多详细信息,请参见Datasette的自定义页面文档。

该网站还提供了Atom最新新闻提要。这是由数据集原子使用此固定SQL查询的输出提供的,并带有此站点插件提供的render_markdown()SQL函数。

我在网站上最兴奋的功能之一就是新的Datasette插件目录。 Datasette现在有50多个插件,而且一段时间以来,我一直想要一个明确的目录。

目前,它非常基本,提供了插件列表以及基于LIKE的简单搜索,但是我计划在将来对其进行大量扩展。

有趣的部分是数据的来源。几年来,我一直在使用GitHub主题来标记我的插件-我用datatete-plugin标记了它们,而我最终启动时计划在网站上展示的插件也用了datatete-io标记。

datasette.io部署过程将运行一个名为build_plugin_directory.py的脚本,该脚本针对GitHub搜索API使用GraphQL查询来查找属于我的所有存储库,这些存储库已被这些标记所标记。

查询{搜索(查询:" topic:datasette-io主题:datasette-plugin用户:simonw"类型:REPOSITORY,首先:100){repositoryCount节点{...在存储库上{id nameWithOwner openGraphImageUrl使用CustomOpenGraphImage repositoryTopics (第一个:100){totalCount个节点{主题{名称}}}} openIssueCount:issue(状态:[OPEN]){totalCount} closeIssueCount:issue(状态:[CLOSED]){totalCount} releases(最后一个:1){totalCount个节点{ 标签名称 } } } } }}

它获取每个存储库的名称,openGraphImageUrl(似乎未包含在常规GitHub REST API中),未解决和已解决的问题数以及最新版本的详细信息。

该脚本有权访问当前站点数据库的副本,该副本由构建脚本在每次部署中下载。它使用它来检查是否任何存储库具有脚本以前未发现的新版本。

然后,它运行github-to-sqlite releases命令(github-to-sqlite的一部分)以获取这些新版本的详细信息。

最终结果是我所有带标签的插件的存储库和发行版的数据库。然后,根据自定义SQL视图构建插件目录。

网站的其余内容主要是静态模板文件。我在其中一些函数中内联使用了render_markdown()函数,因此我可以使用Markdown而不是HTML进行创作-这是/ examples页面的模板。 Datasette页面的各种用例同样被构建为静态模板。

我本周的另一个大型项目涉及为客户端构建一个Datasette实例。为此,我正在处理超过5,000,000行的CSV数据,这是一个极好的机会,可以突破某些工具的限制。

每当我使用新数据时,我都希望对其总体形状有所了解。将5,000,000行的数十列数据导入数据库后,除了在Datasette中浏览列之外,我还能学到什么?

sqlite-utils分析表(此处记录)是我执行此操作的新工具。它遍历数据库中的每个表和每个列,并为每个列计算统计信息,这些统计信息包括:

它可以将它们输出到终端,或者,如果您添加--save选项,它也将它们保存到名为_analyze_tables_的SQLite表中-这是我的github-to-sqlite演示实例的表。

然后,我可以使用该工具的输出来确定哪些列可能是主键,或者哪些列需要使用sqlite-utils提取提取到单独的查找表中。

我希望将来会对此功能进行很多扩展,但是我已经发现它确实很有帮助。

我推出了Datasette的一个小功能版本,以伴随新项目的网站。引用发行说明:

数据集服务具有一个新的--create选项,该选项将创建空白数据库文件(如果尚不存在),而不是错误退出。 (#1135) CSV导出的新?_header = off选项省略了CSV标头行,在此处记录。 (#1133) 项目新闻不再存在于自述文件中,现在可以在https://datasette.io/news中找到。 (#1137) 星期五,我有第一轮Datasette办公时间-与想与我谈论该项目的任何人20分钟的视频聊天。 我进行了五次精彩的交谈,很难夸张地与使用Datasette解决问题的人交谈有多激动。 如果您是开源维护者,则可以彻底尝试使用此格式。 datasette-pretty-json:0.2.1—2020-12-09 Datasette插件,用于漂亮地打印有效的JSON对象或数组的任何列值