diff --git a/datasette/app.py b/datasette/app.py index b768a29885..b8e27f3cbb 100644 --- a/datasette/app.py +++ b/datasette/app.py @@ -56,7 +56,7 @@ resolve_env_secrets, sqlite3, to_css_class, - SpatialiteNotFound, + HASH_LENGTH, ) from .utils.asgi import ( AsgiLifespan, @@ -321,6 +321,10 @@ def __init__( self._root_token = secrets.token_hex(32) self.client = DatasetteClient(self) + @property + def urls(self): + return Urls(self) + async def invoke_startup(self): for hook in pm.hook.startup(datasette=self): await await_me_maybe(hook) @@ -748,6 +752,7 @@ async def render_template( template_context = { **context, **{ + "urls": self.urls, "actor": request.actor if request else None, "display_actor": display_actor, "show_logout": request is not None and "ds_actor" in request.cookies, @@ -1259,3 +1264,28 @@ async def delete(self, path, **kwargs): async def request(self, method, path, **kwargs): async with httpx.AsyncClient(app=self.app) as client: return await client.request(method, self._fix(path), **kwargs) + + +class Urls: + def __init__(self, ds): + self.ds = ds + + def instance(self): + return self.ds.config("base_url") + + def static(self, path): + return "{}-/static/{}".format(self.instance(), path) + + def database(self, database): + db = self.ds.databases[database] + base_url = self.ds.config("base_url") + if self.ds.config("hash_urls") and db.hash: + return "{}{}-{}".format(base_url, database, db.hash[:HASH_LENGTH]) + else: + return "{}{}".format(base_url, database) + + def table(self, database, table): + return "{}/{}".format(self.database(database), urllib.parse.quote_plus(table)) + + def query(self, database, query): + return "{}/{}".format(self.database(database), urllib.parse.quote_plus(query)) diff --git a/datasette/templates/database.html b/datasette/templates/database.html index 5ae51ef7d2..2f844b6a54 100644 --- a/datasette/templates/database.html +++ b/datasette/templates/database.html @@ -11,7 +11,7 @@ {% block nav %}

- home + home

{{ super() }} {% endblock %} @@ -23,7 +23,7 @@

+

Custom SQL query

@@ -36,7 +36,7 @@

Custom SQL query

{% for table in tables %} {% if show_hidden or not table.hidden %}
-

{{ table.name }}{% if table.private %} 🔒{% endif %}{% if table.hidden %} (hidden){% endif %}

+

{{ table.name }}{% if table.private %} 🔒{% endif %}{% if table.hidden %} (hidden){% endif %}

{% for column in table.columns[:9] %}{{ column }}{% if not loop.last %}, {% endif %}{% endfor %}{% if table.columns|length > 9 %}...{% endif %}

{% if table.count is none %}Many rows{% else %}{{ "{:,}".format(table.count) }} row{% if table.count == 1 %}{% else %}s{% endif %}{% endif %}

@@ -44,14 +44,14 @@

{{ table. {% endfor %} {% if hidden_count and not show_hidden %} -

... and {{ "{:,}".format(hidden_count) }} hidden table{% if hidden_count == 1 %}{% else %}s{% endif %}

+

... and {{ "{:,}".format(hidden_count) }} hidden table{% if hidden_count == 1 %}{% else %}s{% endif %}

{% endif %} {% if views %}

Views

{% endif %} @@ -60,13 +60,13 @@

Views

Queries

{% endif %} {% if allow_download %} -

Download SQLite DB: {{ database }}.db {{ format_bytes(size) }}

+

Download SQLite DB: {{ database }}.db {{ format_bytes(size) }}

{% endif %} {% include "_codemirror_foot.html" %} diff --git a/datasette/templates/index.html b/datasette/templates/index.html index c1adfc59d3..06e0963512 100644 --- a/datasette/templates/index.html +++ b/datasette/templates/index.html @@ -10,7 +10,7 @@

{{ metadata.title or "Datasette" }}{% if private %} 🔒{% endif %}

{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %} {% for database in databases %} -

{{ database.name }}{% if database.private %} 🔒{% endif %}

+

{{ database.name }}{% if database.private %} 🔒{% endif %}

{% if database.show_table_row_counts %}{{ "{:,}".format(database.table_rows_sum) }} rows in {% endif %}{{ database.tables_count }} table{% if database.tables_count != 1 %}s{% endif %}{% if database.tables_count and database.hidden_tables_count %}, {% endif -%} {% if database.hidden_tables_count -%} @@ -21,8 +21,7 @@

-

{% for table in database.tables_and_views_truncated %}{{ table.name }}{% if table.private %} 🔒{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}{% if database.tables_and_views_more %}, ...{% endif %}

+

{% for table in database.tables_and_views_truncated %}{{ table.name }}{% if table.private %} 🔒{% endif %}{% if not loop.last %}, {% endif %}{% endfor %}{% if database.tables_and_views_more %}, ...{% endif %}

{% endfor %} {% endblock %} diff --git a/datasette/templates/query.html b/datasette/templates/query.html index be180f3367..911119bb8f 100644 --- a/datasette/templates/query.html +++ b/datasette/templates/query.html @@ -20,8 +20,8 @@ {% block nav %}

- home / - {{ database }} + home / + {{ database }}

{{ super() }} {% endblock %} @@ -32,7 +32,7 @@

+

Custom SQL query{% if display_rows %} returning {% if truncated %}more than {% endif %}{{ "{:,}".format(display_rows|length) }} row{% if display_rows|length == 1 %}{% else %}s{% endif %}{% endif %} {% if hide_sql %}(show){% else %}(hide){% endif %}

{% if not hide_sql %} {% if editable and allow_execute_sql %} diff --git a/datasette/templates/row.html b/datasette/templates/row.html index cd49a4976a..916980b661 100644 --- a/datasette/templates/row.html +++ b/datasette/templates/row.html @@ -17,9 +17,9 @@ {% block nav %}

- home / - {{ database }} / - {{ table }} + home / + {{ database }} / + {{ table }}

{{ super() }} {% endblock %} @@ -38,7 +38,7 @@

Links from other tables