kopia lustrzana https://github.com/simonw/datasette
Rename database->database_name and table-> table_name, refs #1715
rodzic
579f59dcec
commit
7c8fbddb6f
|
@ -68,22 +68,22 @@ class Row:
|
||||||
class TableView(DataView):
|
class TableView(DataView):
|
||||||
name = "table"
|
name = "table"
|
||||||
|
|
||||||
async def sortable_columns_for_table(self, database, table, use_rowid):
|
async def sortable_columns_for_table(self, database_name, table_name, use_rowid):
|
||||||
db = self.ds.databases[database]
|
db = self.ds.databases[database_name]
|
||||||
table_metadata = self.ds.table_metadata(database, table)
|
table_metadata = self.ds.table_metadata(database_name, table_name)
|
||||||
if "sortable_columns" in table_metadata:
|
if "sortable_columns" in table_metadata:
|
||||||
sortable_columns = set(table_metadata["sortable_columns"])
|
sortable_columns = set(table_metadata["sortable_columns"])
|
||||||
else:
|
else:
|
||||||
sortable_columns = set(await db.table_columns(table))
|
sortable_columns = set(await db.table_columns(table_name))
|
||||||
if use_rowid:
|
if use_rowid:
|
||||||
sortable_columns.add("rowid")
|
sortable_columns.add("rowid")
|
||||||
return sortable_columns
|
return sortable_columns
|
||||||
|
|
||||||
async def expandable_columns(self, database, table):
|
async def expandable_columns(self, database_name, table_name):
|
||||||
# Returns list of (fk_dict, label_column-or-None) pairs for that table
|
# Returns list of (fk_dict, label_column-or-None) pairs for that table
|
||||||
expandables = []
|
expandables = []
|
||||||
db = self.ds.databases[database]
|
db = self.ds.databases[database_name]
|
||||||
for fk in await db.foreign_keys_for_table(table):
|
for fk in await db.foreign_keys_for_table(table_name):
|
||||||
label_column = await db.label_column_for_table(fk["other_table"])
|
label_column = await db.label_column_for_table(fk["other_table"])
|
||||||
expandables.append((fk, label_column))
|
expandables.append((fk, label_column))
|
||||||
return expandables
|
return expandables
|
||||||
|
@ -94,17 +94,19 @@ class TableView(DataView):
|
||||||
db = self.ds.get_database(route=database_route)
|
db = self.ds.get_database(route=database_route)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise NotFound("Database not found: {}".format(database_route))
|
raise NotFound("Database not found: {}".format(database_route))
|
||||||
database = db.name
|
database_name = db.name
|
||||||
table = tilde_decode(request.url_vars["table"])
|
table_name = tilde_decode(request.url_vars["table"])
|
||||||
# Handle POST to a canned query
|
# Handle POST to a canned query
|
||||||
canned_query = await self.ds.get_canned_query(database, table, request.actor)
|
canned_query = await self.ds.get_canned_query(
|
||||||
|
database_name, table_name, request.actor
|
||||||
|
)
|
||||||
assert canned_query, "You may only POST to a canned query"
|
assert canned_query, "You may only POST to a canned query"
|
||||||
return await QueryView(self.ds).data(
|
return await QueryView(self.ds).data(
|
||||||
request,
|
request,
|
||||||
canned_query["sql"],
|
canned_query["sql"],
|
||||||
metadata=canned_query,
|
metadata=canned_query,
|
||||||
editable=False,
|
editable=False,
|
||||||
canned_query=table,
|
canned_query=table_name,
|
||||||
named_parameters=canned_query.get("params"),
|
named_parameters=canned_query.get("params"),
|
||||||
write=bool(canned_query.get("write")),
|
write=bool(canned_query.get("write")),
|
||||||
)
|
)
|
||||||
|
@ -150,45 +152,47 @@ class TableView(DataView):
|
||||||
_size=None,
|
_size=None,
|
||||||
):
|
):
|
||||||
database_route = tilde_decode(request.url_vars["database"])
|
database_route = tilde_decode(request.url_vars["database"])
|
||||||
table = tilde_decode(request.url_vars["table"])
|
table_name = tilde_decode(request.url_vars["table"])
|
||||||
try:
|
try:
|
||||||
db = self.ds.get_database(route=database_route)
|
db = self.ds.get_database(route=database_route)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
raise NotFound("Database not found: {}".format(database_route))
|
raise NotFound("Database not found: {}".format(database_route))
|
||||||
database = db.name
|
database_name = db.name
|
||||||
|
|
||||||
# If this is a canned query, not a table, then dispatch to QueryView instead
|
# If this is a canned query, not a table, then dispatch to QueryView instead
|
||||||
canned_query = await self.ds.get_canned_query(database, table, request.actor)
|
canned_query = await self.ds.get_canned_query(
|
||||||
|
database_name, table_name, request.actor
|
||||||
|
)
|
||||||
if canned_query:
|
if canned_query:
|
||||||
return await QueryView(self.ds).data(
|
return await QueryView(self.ds).data(
|
||||||
request,
|
request,
|
||||||
canned_query["sql"],
|
canned_query["sql"],
|
||||||
metadata=canned_query,
|
metadata=canned_query,
|
||||||
editable=False,
|
editable=False,
|
||||||
canned_query=table,
|
canned_query=table_name,
|
||||||
named_parameters=canned_query.get("params"),
|
named_parameters=canned_query.get("params"),
|
||||||
write=bool(canned_query.get("write")),
|
write=bool(canned_query.get("write")),
|
||||||
)
|
)
|
||||||
|
|
||||||
is_view = bool(await db.get_view_definition(table))
|
is_view = bool(await db.get_view_definition(table_name))
|
||||||
table_exists = bool(await db.table_exists(table))
|
table_exists = bool(await db.table_exists(table_name))
|
||||||
|
|
||||||
# If table or view not found, return 404
|
# If table or view not found, return 404
|
||||||
if not is_view and not table_exists:
|
if not is_view and not table_exists:
|
||||||
raise NotFound(f"Table not found: {table}")
|
raise NotFound(f"Table not found: {table_name}")
|
||||||
|
|
||||||
# Ensure user has permission to view this table
|
# Ensure user has permission to view this table
|
||||||
await self.ds.ensure_permissions(
|
await self.ds.ensure_permissions(
|
||||||
request.actor,
|
request.actor,
|
||||||
[
|
[
|
||||||
("view-table", (database, table)),
|
("view-table", (database_name, table_name)),
|
||||||
("view-database", database),
|
("view-database", database_name),
|
||||||
"view-instance",
|
"view-instance",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
private = not await self.ds.permission_allowed(
|
private = not await self.ds.permission_allowed(
|
||||||
None, "view-table", (database, table), default=True
|
None, "view-table", (database_name, table_name), default=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# Handle ?_filter_column and redirect, if present
|
# Handle ?_filter_column and redirect, if present
|
||||||
|
@ -216,8 +220,8 @@ class TableView(DataView):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Introspect columns and primary keys for table
|
# Introspect columns and primary keys for table
|
||||||
pks = await db.primary_keys(table)
|
pks = await db.primary_keys(table_name)
|
||||||
table_columns = await db.table_columns(table)
|
table_columns = await db.table_columns(table_name)
|
||||||
|
|
||||||
# Take ?_col= and ?_nocol= into account
|
# Take ?_col= and ?_nocol= into account
|
||||||
specified_columns = await self.columns_to_select(table_columns, pks, request)
|
specified_columns = await self.columns_to_select(table_columns, pks, request)
|
||||||
|
@ -248,7 +252,7 @@ class TableView(DataView):
|
||||||
nocount = True
|
nocount = True
|
||||||
nofacet = True
|
nofacet = True
|
||||||
|
|
||||||
table_metadata = self.ds.table_metadata(database, table)
|
table_metadata = self.ds.table_metadata(database_name, table_name)
|
||||||
units = table_metadata.get("units", {})
|
units = table_metadata.get("units", {})
|
||||||
|
|
||||||
# Arguments that start with _ and don't contain a __ are
|
# Arguments that start with _ and don't contain a __ are
|
||||||
|
@ -262,7 +266,7 @@ class TableView(DataView):
|
||||||
|
|
||||||
# Build where clauses from query string arguments
|
# Build where clauses from query string arguments
|
||||||
filters = Filters(sorted(filter_args), units, ureg)
|
filters = Filters(sorted(filter_args), units, ureg)
|
||||||
where_clauses, params = filters.build_where_clauses(table)
|
where_clauses, params = filters.build_where_clauses(table_name)
|
||||||
|
|
||||||
# Execute filters_from_request plugin hooks - including the default
|
# Execute filters_from_request plugin hooks - including the default
|
||||||
# ones that live in datasette/filters.py
|
# ones that live in datasette/filters.py
|
||||||
|
@ -271,8 +275,8 @@ class TableView(DataView):
|
||||||
|
|
||||||
for hook in pm.hook.filters_from_request(
|
for hook in pm.hook.filters_from_request(
|
||||||
request=request,
|
request=request,
|
||||||
table=table,
|
table=table_name,
|
||||||
database=database,
|
database=database_name,
|
||||||
datasette=self.ds,
|
datasette=self.ds,
|
||||||
):
|
):
|
||||||
filter_arguments = await await_me_maybe(hook)
|
filter_arguments = await await_me_maybe(hook)
|
||||||
|
@ -284,7 +288,7 @@ class TableView(DataView):
|
||||||
|
|
||||||
# Deal with custom sort orders
|
# Deal with custom sort orders
|
||||||
sortable_columns = await self.sortable_columns_for_table(
|
sortable_columns = await self.sortable_columns_for_table(
|
||||||
database, table, use_rowid
|
database_name, table_name, use_rowid
|
||||||
)
|
)
|
||||||
sort = request.args.get("_sort")
|
sort = request.args.get("_sort")
|
||||||
sort_desc = request.args.get("_sort_desc")
|
sort_desc = request.args.get("_sort_desc")
|
||||||
|
@ -309,7 +313,7 @@ class TableView(DataView):
|
||||||
order_by = f"{escape_sqlite(sort_desc)} desc"
|
order_by = f"{escape_sqlite(sort_desc)} desc"
|
||||||
|
|
||||||
from_sql = "from {table_name} {where}".format(
|
from_sql = "from {table_name} {where}".format(
|
||||||
table_name=escape_sqlite(table),
|
table_name=escape_sqlite(table_name),
|
||||||
where=("where {} ".format(" and ".join(where_clauses)))
|
where=("where {} ".format(" and ".join(where_clauses)))
|
||||||
if where_clauses
|
if where_clauses
|
||||||
else "",
|
else "",
|
||||||
|
@ -422,7 +426,7 @@ class TableView(DataView):
|
||||||
sql_no_order_no_limit = (
|
sql_no_order_no_limit = (
|
||||||
"select {select_all_columns} from {table_name} {where}".format(
|
"select {select_all_columns} from {table_name} {where}".format(
|
||||||
select_all_columns=select_all_columns,
|
select_all_columns=select_all_columns,
|
||||||
table_name=escape_sqlite(table),
|
table_name=escape_sqlite(table_name),
|
||||||
where=where_clause,
|
where=where_clause,
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
@ -430,7 +434,7 @@ class TableView(DataView):
|
||||||
# This is the SQL that populates the main table on the page
|
# This is the SQL that populates the main table on the page
|
||||||
sql = "select {select_specified_columns} from {table_name} {where}{order_by} limit {page_size}{offset}".format(
|
sql = "select {select_specified_columns} from {table_name} {where}{order_by} limit {page_size}{offset}".format(
|
||||||
select_specified_columns=select_specified_columns,
|
select_specified_columns=select_specified_columns,
|
||||||
table_name=escape_sqlite(table),
|
table_name=escape_sqlite(table_name),
|
||||||
where=where_clause,
|
where=where_clause,
|
||||||
order_by=order_by,
|
order_by=order_by,
|
||||||
page_size=page_size + 1,
|
page_size=page_size + 1,
|
||||||
|
@ -448,13 +452,13 @@ class TableView(DataView):
|
||||||
if (
|
if (
|
||||||
not db.is_mutable
|
not db.is_mutable
|
||||||
and self.ds.inspect_data
|
and self.ds.inspect_data
|
||||||
and count_sql == f"select count(*) from {table} "
|
and count_sql == f"select count(*) from {table_name} "
|
||||||
):
|
):
|
||||||
# We can use a previously cached table row count
|
# We can use a previously cached table row count
|
||||||
try:
|
try:
|
||||||
filtered_table_rows_count = self.ds.inspect_data[database]["tables"][
|
filtered_table_rows_count = self.ds.inspect_data[database_name][
|
||||||
table
|
"tables"
|
||||||
]["count"]
|
][table_name]["count"]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
@ -484,10 +488,10 @@ class TableView(DataView):
|
||||||
klass(
|
klass(
|
||||||
self.ds,
|
self.ds,
|
||||||
request,
|
request,
|
||||||
database,
|
database_name,
|
||||||
sql=sql_no_order_no_limit,
|
sql=sql_no_order_no_limit,
|
||||||
params=params,
|
params=params,
|
||||||
table=table,
|
table=table_name,
|
||||||
metadata=table_metadata,
|
metadata=table_metadata,
|
||||||
row_count=filtered_table_rows_count,
|
row_count=filtered_table_rows_count,
|
||||||
)
|
)
|
||||||
|
@ -527,7 +531,7 @@ class TableView(DataView):
|
||||||
|
|
||||||
# Expand labeled columns if requested
|
# Expand labeled columns if requested
|
||||||
expanded_columns = []
|
expanded_columns = []
|
||||||
expandable_columns = await self.expandable_columns(database, table)
|
expandable_columns = await self.expandable_columns(database_name, table_name)
|
||||||
columns_to_expand = None
|
columns_to_expand = None
|
||||||
try:
|
try:
|
||||||
all_labels = value_as_boolean(request.args.get("_labels", ""))
|
all_labels = value_as_boolean(request.args.get("_labels", ""))
|
||||||
|
@ -554,7 +558,9 @@ class TableView(DataView):
|
||||||
values = [row[column_index] for row in rows]
|
values = [row[column_index] for row in rows]
|
||||||
# Expand them
|
# Expand them
|
||||||
expanded_labels.update(
|
expanded_labels.update(
|
||||||
await self.ds.expand_foreign_keys(database, table, column, values)
|
await self.ds.expand_foreign_keys(
|
||||||
|
database_name, table_name, column, values
|
||||||
|
)
|
||||||
)
|
)
|
||||||
if expanded_labels:
|
if expanded_labels:
|
||||||
# Rewrite the rows
|
# Rewrite the rows
|
||||||
|
@ -621,21 +627,21 @@ class TableView(DataView):
|
||||||
|
|
||||||
display_columns, display_rows = await display_columns_and_rows(
|
display_columns, display_rows = await display_columns_and_rows(
|
||||||
self.ds,
|
self.ds,
|
||||||
database,
|
database_name,
|
||||||
table,
|
table_name,
|
||||||
results.description,
|
results.description,
|
||||||
rows,
|
rows,
|
||||||
link_column=not is_view,
|
link_column=not is_view,
|
||||||
truncate_cells=self.ds.setting("truncate_cells_html"),
|
truncate_cells=self.ds.setting("truncate_cells_html"),
|
||||||
sortable_columns=await self.sortable_columns_for_table(
|
sortable_columns=await self.sortable_columns_for_table(
|
||||||
database, table, use_rowid=True
|
database_name, table_name, use_rowid=True
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
metadata = (
|
metadata = (
|
||||||
(self.ds.metadata("databases") or {})
|
(self.ds.metadata("databases") or {})
|
||||||
.get(database, {})
|
.get(database_name, {})
|
||||||
.get("tables", {})
|
.get("tables", {})
|
||||||
.get(table, {})
|
.get(table_name, {})
|
||||||
)
|
)
|
||||||
self.ds.update_with_inherited_metadata(metadata)
|
self.ds.update_with_inherited_metadata(metadata)
|
||||||
|
|
||||||
|
@ -661,8 +667,8 @@ class TableView(DataView):
|
||||||
links = []
|
links = []
|
||||||
for hook in pm.hook.table_actions(
|
for hook in pm.hook.table_actions(
|
||||||
datasette=self.ds,
|
datasette=self.ds,
|
||||||
table=table,
|
table=table_name,
|
||||||
database=database,
|
database=database_name,
|
||||||
actor=request.actor,
|
actor=request.actor,
|
||||||
request=request,
|
request=request,
|
||||||
):
|
):
|
||||||
|
@ -703,13 +709,13 @@ class TableView(DataView):
|
||||||
"sort_desc": sort_desc,
|
"sort_desc": sort_desc,
|
||||||
"disable_sort": is_view,
|
"disable_sort": is_view,
|
||||||
"custom_table_templates": [
|
"custom_table_templates": [
|
||||||
f"_table-{to_css_class(database)}-{to_css_class(table)}.html",
|
f"_table-{to_css_class(database_name)}-{to_css_class(table_name)}.html",
|
||||||
f"_table-table-{to_css_class(database)}-{to_css_class(table)}.html",
|
f"_table-table-{to_css_class(database_name)}-{to_css_class(table_name)}.html",
|
||||||
"_table.html",
|
"_table.html",
|
||||||
],
|
],
|
||||||
"metadata": metadata,
|
"metadata": metadata,
|
||||||
"view_definition": await db.get_view_definition(table),
|
"view_definition": await db.get_view_definition(table_name),
|
||||||
"table_definition": await db.get_table_definition(table),
|
"table_definition": await db.get_table_definition(table_name),
|
||||||
"datasette_allow_facet": "true"
|
"datasette_allow_facet": "true"
|
||||||
if self.ds.setting("allow_facet")
|
if self.ds.setting("allow_facet")
|
||||||
else "false",
|
else "false",
|
||||||
|
@ -719,8 +725,8 @@ class TableView(DataView):
|
||||||
|
|
||||||
return (
|
return (
|
||||||
{
|
{
|
||||||
"database": database,
|
"database": database_name,
|
||||||
"table": table,
|
"table": table_name,
|
||||||
"is_view": is_view,
|
"is_view": is_view,
|
||||||
"human_description_en": human_description_en,
|
"human_description_en": human_description_en,
|
||||||
"rows": rows[:page_size],
|
"rows": rows[:page_size],
|
||||||
|
@ -738,12 +744,12 @@ class TableView(DataView):
|
||||||
"next_url": next_url,
|
"next_url": next_url,
|
||||||
"private": private,
|
"private": private,
|
||||||
"allow_execute_sql": await self.ds.permission_allowed(
|
"allow_execute_sql": await self.ds.permission_allowed(
|
||||||
request.actor, "execute-sql", database, default=True
|
request.actor, "execute-sql", database_name, default=True
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
extra_template,
|
extra_template,
|
||||||
(
|
(
|
||||||
f"table-{to_css_class(database)}-{to_css_class(table)}.html",
|
f"table-{to_css_class(database_name)}-{to_css_class(table_name)}.html",
|
||||||
"table.html",
|
"table.html",
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
@ -766,8 +772,8 @@ async def _sql_params_pks(db, table, pk_values):
|
||||||
|
|
||||||
async def display_columns_and_rows(
|
async def display_columns_and_rows(
|
||||||
datasette,
|
datasette,
|
||||||
database,
|
database_name,
|
||||||
table,
|
table_name,
|
||||||
description,
|
description,
|
||||||
rows,
|
rows,
|
||||||
link_column=False,
|
link_column=False,
|
||||||
|
@ -776,11 +782,13 @@ async def display_columns_and_rows(
|
||||||
):
|
):
|
||||||
"""Returns columns, rows for specified table - including fancy foreign key treatment"""
|
"""Returns columns, rows for specified table - including fancy foreign key treatment"""
|
||||||
sortable_columns = sortable_columns or set()
|
sortable_columns = sortable_columns or set()
|
||||||
db = datasette.databases[database]
|
db = datasette.databases[database_name]
|
||||||
table_metadata = datasette.table_metadata(database, table)
|
table_metadata = datasette.table_metadata(database_name, table_name)
|
||||||
column_descriptions = table_metadata.get("columns") or {}
|
column_descriptions = table_metadata.get("columns") or {}
|
||||||
column_details = {col.name: col for col in await db.table_column_details(table)}
|
column_details = {
|
||||||
pks = await db.primary_keys(table)
|
col.name: col for col in await db.table_column_details(table_name)
|
||||||
|
}
|
||||||
|
pks = await db.primary_keys(table_name)
|
||||||
pks_for_display = pks
|
pks_for_display = pks
|
||||||
if not pks_for_display:
|
if not pks_for_display:
|
||||||
pks_for_display = ["rowid"]
|
pks_for_display = ["rowid"]
|
||||||
|
@ -805,7 +813,8 @@ async def display_columns_and_rows(
|
||||||
)
|
)
|
||||||
|
|
||||||
column_to_foreign_key_table = {
|
column_to_foreign_key_table = {
|
||||||
fk["column"]: fk["other_table"] for fk in await db.foreign_keys_for_table(table)
|
fk["column"]: fk["other_table"]
|
||||||
|
for fk in await db.foreign_keys_for_table(table_name)
|
||||||
}
|
}
|
||||||
|
|
||||||
cell_rows = []
|
cell_rows = []
|
||||||
|
@ -826,7 +835,7 @@ async def display_columns_and_rows(
|
||||||
"value": markupsafe.Markup(
|
"value": markupsafe.Markup(
|
||||||
'<a href="{table_path}/{flat_pks_quoted}">{flat_pks}</a>'.format(
|
'<a href="{table_path}/{flat_pks_quoted}">{flat_pks}</a>'.format(
|
||||||
base_url=base_url,
|
base_url=base_url,
|
||||||
table_path=datasette.urls.table(database, table),
|
table_path=datasette.urls.table(database_name, table_name),
|
||||||
flat_pks=str(markupsafe.escape(pk_path)),
|
flat_pks=str(markupsafe.escape(pk_path)),
|
||||||
flat_pks_quoted=path_from_row_pks(row, pks, not pks),
|
flat_pks_quoted=path_from_row_pks(row, pks, not pks),
|
||||||
)
|
)
|
||||||
|
@ -847,8 +856,8 @@ async def display_columns_and_rows(
|
||||||
for candidate in pm.hook.render_cell(
|
for candidate in pm.hook.render_cell(
|
||||||
value=value,
|
value=value,
|
||||||
column=column,
|
column=column,
|
||||||
table=table,
|
table=table_name,
|
||||||
database=database,
|
database=database_name,
|
||||||
datasette=datasette,
|
datasette=datasette,
|
||||||
):
|
):
|
||||||
candidate = await await_me_maybe(candidate)
|
candidate = await await_me_maybe(candidate)
|
||||||
|
@ -862,8 +871,8 @@ async def display_columns_and_rows(
|
||||||
display_value = markupsafe.Markup(
|
display_value = markupsafe.Markup(
|
||||||
'<a class="blob-download" href="{}"{}><Binary: {:,} byte{}></a>'.format(
|
'<a class="blob-download" href="{}"{}><Binary: {:,} byte{}></a>'.format(
|
||||||
datasette.urls.row_blob(
|
datasette.urls.row_blob(
|
||||||
database,
|
database_name,
|
||||||
table,
|
table_name,
|
||||||
path_from_row_pks(row, pks, not pks),
|
path_from_row_pks(row, pks, not pks),
|
||||||
column,
|
column,
|
||||||
),
|
),
|
||||||
|
@ -883,7 +892,7 @@ async def display_columns_and_rows(
|
||||||
link_template = LINK_WITH_LABEL if (label != value) else LINK_WITH_VALUE
|
link_template = LINK_WITH_LABEL if (label != value) else LINK_WITH_VALUE
|
||||||
display_value = markupsafe.Markup(
|
display_value = markupsafe.Markup(
|
||||||
link_template.format(
|
link_template.format(
|
||||||
database=database,
|
database=database_name,
|
||||||
base_url=base_url,
|
base_url=base_url,
|
||||||
table=tilde_encode(other_table),
|
table=tilde_encode(other_table),
|
||||||
link_id=tilde_encode(str(value)),
|
link_id=tilde_encode(str(value)),
|
||||||
|
|
Ładowanie…
Reference in New Issue