mirror of
https://github.com/simonw/datasette.git
synced 2025-12-10 16:51:24 +01:00
These new querystring arguments can be used to request expanded foreign keys
in both JSON and CSV formats.
?_labels=on turns on expansions for ALL foreign key columns
?_label=COLUMN1&_label=COLUMN2 can be used to pick specific columns to expand
e.g. `Street_Tree_List.json?_label=qSpecies&_label=qLegalStatus`
{
"rowid": 233,
"TreeID": 121240,
"qLegalStatus": {
"value" 2,
"label": "Private"
}
"qSpecies": {
"value": 16,
"label": "Sycamore"
}
"qAddress": "91 Commonwealth Ave",
...
}
The labels option also works for the HTML and CSV views.
HTML defaults to `?_labels=on`, so if you pass `?_labels=off` you can disable
foreign key expansion entirely - or you can use `?_label=COLUMN` to request
just specific columns.
If you expand labels on CSV you get additional columns in the output:
`/Street_Tree_List.csv?_label=qLegalStatus`
rowid,TreeID,qLegalStatus,qLegalStatus_label...
1,141565,1,Permitted Site...
2,232565,2,Undocumented...
I also refactored the existing foreign key expansion code.
Closes #233. Refs #266.
55 lines
1.9 KiB
Python
55 lines
1.9 KiB
Python
import os
|
|
|
|
from sanic import response
|
|
|
|
from datasette.utils import to_css_class, validate_sql_select
|
|
|
|
from .base import BaseView, DatasetteError
|
|
|
|
|
|
class DatabaseView(BaseView):
|
|
|
|
async def data(self, request, name, hash, default_labels=False):
|
|
if request.args.get("sql"):
|
|
if not self.ds.config["allow_sql"]:
|
|
raise DatasetteError("sql= is not allowed", status=400)
|
|
sql = request.raw_args.pop("sql")
|
|
validate_sql_select(sql)
|
|
return await self.custom_sql(request, name, hash, sql)
|
|
|
|
info = self.ds.inspect()[name]
|
|
metadata = self.ds.metadata.get("databases", {}).get(name, {})
|
|
self.ds.update_with_inherited_metadata(metadata)
|
|
tables = list(info["tables"].values())
|
|
tables.sort(key=lambda t: (t["hidden"], t["name"]))
|
|
return {
|
|
"database": name,
|
|
"tables": tables,
|
|
"hidden_count": len([t for t in tables if t["hidden"]]),
|
|
"views": info["views"],
|
|
"queries": [
|
|
{"name": query_name, "sql": query_sql}
|
|
for query_name, query_sql in (metadata.get("queries") or {}).items()
|
|
],
|
|
"config": self.ds.config,
|
|
}, {
|
|
"database_hash": hash,
|
|
"show_hidden": request.args.get("_show_hidden"),
|
|
"editable": True,
|
|
"metadata": metadata,
|
|
}, (
|
|
"database-{}.html".format(to_css_class(name)), "database.html"
|
|
)
|
|
|
|
|
|
class DatabaseDownload(BaseView):
|
|
|
|
async def view_get(self, request, name, hash, **kwargs):
|
|
if not self.ds.config["allow_download"]:
|
|
raise DatasetteError("Database download is forbidden", status=403)
|
|
filepath = self.ds.inspect()[name]["file"]
|
|
return await response.file_stream(
|
|
filepath,
|
|
filename=os.path.basename(filepath),
|
|
mime_type="application/octet-stream",
|
|
)
|