提供SQLite数据库自动GraphQL API的Datasette插件
项目描述
datasette-graphql
提供SQLite数据库自动GraphQL API的Datasette插件
了解此项目的更多信息: 使用新的datasette-graphql插件在Datasette中实现GraphQL
在 datasette-graphql-demo.datasette.io/graphql 尝试实时演示
安装
在Datasette相同的环境中安装此插件。
$ datasette install datasette-graphql
配置
默认情况下,此插件将在/graphql
处添加GraphQL API。您可以使用path
插件设置配置不同的路径,例如,通过将以下内容添加到metadata.json
{
"plugins": {
"datasette-graphql": {
"path": "/-/graphql"
}
}
}
这将设置GraphQL API以在/-/graphql
处运行。
使用
此插件将/graphql
设置为第一个附加数据库的GraphQL端点。
如果您有多个附加数据库,每个数据库都将有自己的端点/graphql/数据库名称
。
自动生成的GraphQL模式在/graphql/数据库名称.graphql
处可用 - 这里是一个示例。
查询表和列
可以像这样查询单个表(以及SQL视图)
{
repos {
nodes {
id
full_name
description_
}
}
}
在此示例查询中,底层数据库表名为repos
,其列包括id
、full_name
和description
。由于description
是一个保留字,因此查询需要请求description_
。
获取单个记录
如果您只想获取一条记录——例如,如果您想通过其主键获取一行——则可以使用tablename_row
字段
{
repos_row(id: 107914493) {
id
full_name
description_
}
}
tablename_row
字段接受主键列(或列)作为参数。它也支持与下面描述的tablename
字段相同的filter:
、search:
、sort:
和sort_desc:
参数。
访问嵌套对象
如果某列是另一个表的外键,您可以使用如下嵌套查询请求该外键指向的表中的列
{
repos {
nodes {
id
full_name
owner {
id
login
}
}
}
}
访问相关对象
如果另一个表有一个外键指向您正在访问的表,您可以从该相关表获取行。
考虑一个users
表,它与repos
相关——一个仓库有一个外键指向拥有该仓库的用户。users
对象类型将有一个repos_by_owner_list
字段,可以用来访问这些相关仓库
{
users(first: 1, search: "simonw") {
nodes {
name
repos_by_owner_list(first: 5) {
totalCount
nodes {
full_name
}
}
}
}
}
过滤表
您可以使用filter:
参数来过滤特定表返回的行。这个参数接受一个将列映射到操作的过滤器对象。例如,返回只有Apache 2许可证并且有超过10个星级的存储库
{
repos(filter: {license: {eq: "apache-2.0"}, stargazers_count: {gt: 10}}) {
nodes {
full_name
stargazers_count
license {
key
}
}
}
}
有关更多操作,请参阅表过滤器示例,以及Datasette文档中的列过滤器参数的详细信息。
这些相同的过滤器也可以用于嵌套关系,如下所示
{
users_row(id: 9599) {
name
repos_by_owner_list(filter: {name: {startswith: "datasette-"}}) {
totalCount
nodes {
full_name
}
}
}
}
当您要表达的内容过于复杂,无法用过滤器表达式建模时,可以使用where:
参数作为filter:
的替代。它接受一个字符串片段SQL,该片段将被包含在SQL查询的WHERE
子句中。
{
repos(where: "name='sqlite-utils' or name like 'datasette-%'") {
totalCount
nodes {
full_name
}
}
}
排序
您可以使用sort:
或sort_desc:
参数为表的结果设置排序顺序。此参数的值应该是您希望按其排序(或降序排序)的列名。
{
repos(sort_desc: stargazers_count) {
nodes {
full_name
stargazers_count
}
}
}
分页
默认情况下,将返回前10行。您可以使用first:
参数来控制这一点。
{
repos(first: 20) {
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
full_name
stargazers_count
license {
key
}
}
}
}
totalCount
字段返回与查询匹配的记录总数。
请求pageInfo.endCursor
字段可以为您提供请求下一页所需的价值。您可以将其传递给after:
参数以请求下一页。
{
repos(first: 20, after: "134874019") {
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
full_name
stargazers_count
license {
key
}
}
}
}
hasNextPage
字段告诉您是否还有更多记录。
搜索
如果已配置表使用SQLite全文搜索,您可以使用search:
参数执行对其的搜索
{
repos(search: "datasette") {
totalCount
pageInfo {
hasNextPage
endCursor
}
nodes {
full_name
description_
}
}
}
可以使用sqlite-utils Python库和CLI工具将全文搜索添加到现有的数据库表。
包含JSON字符串的列
如果您的表有一个包含作为JSON编码的数据的列,datasette-graphql
将使该列作为编码的JSON字符串可用。调用您的API的客户端需要将字符串解析为JSON才能访问数据。
您可以通过将列配置为JSON列来以嵌套结构返回数据。在metadata.json
中的配置如下
{
"databases": {
"test": {
"tables": {
"repos": {
"plugins": {
"datasette-graphql": {
"json_columns": [
"tags"
]
}
}
}
}
}
}
}
自动camelCase
您的列和表的名称默认与GraphQL中的表示匹配。
如果您有names_like_this
格式的表,您可能希望在GraphQL中使用namesLikeThis
来与GraphQL和JavaScript约定保持一致。
您可以通过在metadata.json
中使用"auto_camelcase"
插件配置设置来打开自动camelCase。
{
"plugins": {
"datasette-graphql": {
"auto_camelcase": true
}
}
}
CORS
此插件遵循传递给 datasette
命令行工具的 --cors
选项。如果您传递了 --cors
,它将添加以下 CORS HTTP 头,以允许在其它域上运行的 JavaScript 访问 GraphQL API
access-control-allow-headers: content-type
access-control-allow-method: POST
access-control-allow-origin: *
执行限制
插件默认实现两个限制
- 构成 GraphQL 执行的所有底层 SQL 查询的总执行时间必须不超过 1000ms(一秒)
- 由于嵌套 GraphQL 字段而执行的 SQL 表查询总数不得超过 100
可以使用 num_queries_limit
和 time_limit_ms
插件配置设置来自定义这些限制,例如在 metadata.json
中
{
"plugins": {
"datasette-graphql": {
"num_queries_limit": 200,
"time_limit_ms": 5000
}
}
}
将它们设置为 0
将完全禁用限制检查。
graphql()模板函数
插件还提供了一个名为 graphql()
的 Jinja 模板函数。您可以在 Datasette 的 自定义模板 中使用该函数,如下所示
{% set users = graphql("""
{
users {
nodes {
name
points
score
}
}
}
""")["users"] %}
{% for user in users.nodes %}
<p>{{ user.name }} - points: {{ user.points }}, score = {{ user.score }}</p>
{% endfor %}
该函数将执行针对生成的模式的 GraphQL 查询并返回结果。您可以将这些结果分配给模板中的一个变量,然后遍历并显示它们。
默认情况下,查询将针对第一个附加的数据库运行。您可以使用函数的可选第二个参数来指定不同的数据库 - 例如,要针对附加的 github.db
数据库运行,您将这样做
{% set user = graphql("""
{
users_row(id:9599) {
name
login
avatar_url
}
}
""", "github")["users_row"] %}
<h1>Hello, {{ user.name }}</h1>
您可以通过传递到 variables=
参数中,在模板调用中使用 GraphQL 变量
{% set user = graphql("""
query ($id: Int) {
users_row(id: $id) {
name
login
avatar_url
}
}
""", database="github", variables={"id": 9599})["users_row"] %}
<h1>Hello, {{ user.name }}</h1>
使用插件添加自定义字段
datasette-graphql
为 Datasette 添加了一个新的 插件钩子,可用于向您的 GraphQL 模式添加自定义字段。
插件钩子如下所示
@hookimpl
def graphql_extra_fields(datasette, database):
"A list of (name, field_type) tuples to include in the GraphQL schema"
您可以使用此钩子返回一个描述应公开在您模式中的附加字段的元组的列表。每个元组应包含一个命名新字段的字符串,以及一个指定模式和提供 resolver
函数的 Graphene 字段对象。
此示例实现使用 pkg_resources
返回当前安装的 Python 包列表
import graphene
from datasette import hookimpl
import pkg_resources
@hookimpl
def graphql_extra_fields():
class Package(graphene.ObjectType):
"An installed package"
name = graphene.String()
version = graphene.String()
def resolve_packages(root, info):
return [
{"name": d.project_name, "version": d.version}
for d in pkg_resources.working_set
]
return [
(
"packages",
graphene.Field(
graphene.List(Package),
description="List of installed packages",
resolver=resolve_packages,
),
),
]
安装此插件后,可以使用以下 GraphQL 查询检索安装包列表
{
packages {
name
version
}
}
开发
要本地设置此插件,首先检出代码。然后创建一个新的虚拟环境
cd datasette-graphql
python3 -mvenv venv
source venv/bin/activate
或者如果您正在使用 pipenv
pipenv shell
现在安装依赖项和测试
pip install -e '.[test]'
要运行测试
pytest
项目详细信息
下载文件
下载适用于您平台的应用程序。如果您不确定选择哪个,请了解有关安装包的更多信息。