metadata.json support for per-table/per-database metadata

Also added support for descriptions and HTML descriptions.

Here's an example metadata.json file illustrating custom per-database and per-
table metadata:

    {
        "title": "Overall datasette title",
        "description_html": "This is a <em>description with HTML</em>.",
        "databases": {
            "db1": {
                "title": "First database",
                "description": "This is a string description & has no HTML",
                "license_url": "http://example.com/",
        		"license": "The example license",
                "queries": {
                	"canned_query": "select * from table1 limit 3;"
                },
                "tables": {
                    "table1": {
                        "title": "Custom title for table1",
                        "description": "Tables can have descriptions too",
                        "source": "This has a custom source",
                        "source_url": "http://example.com/"
                    }
                }
            }
        }
    }

Closes #165, Refs #164
This commit is contained in:
Simon Willison 2017-12-07 08:42:54 -08:00
commit 80bf3afa43
No known key found for this signature in database
GPG key ID: 17E2DEA2588B7F52
7 changed files with 54 additions and 31 deletions

View file

@ -242,12 +242,13 @@ class BaseView(RenderMixin):
**{ **{
'url_json': path_with_ext(request, '.json'), 'url_json': path_with_ext(request, '.json'),
'url_jsono': path_with_ext(request, '.jsono'), 'url_jsono': path_with_ext(request, '.jsono'),
'metadata': self.ds.metadata,
'extra_css_urls': self.ds.extra_css_urls(), 'extra_css_urls': self.ds.extra_css_urls(),
'extra_js_urls': self.ds.extra_js_urls(), 'extra_js_urls': self.ds.extra_js_urls(),
'datasette_version': __version__, 'datasette_version': __version__,
} }
} }
if 'metadata' not in context:
context['metadata'] = self.ds.metadata
r = self.render( r = self.render(
templates, templates,
**context, **context,
@ -379,6 +380,9 @@ class DatabaseView(BaseView):
'database_hash': hash, 'database_hash': hash,
'show_hidden': request.args.get('_show_hidden'), 'show_hidden': request.args.get('_show_hidden'),
'editable': True, 'editable': True,
'metadata': self.ds.metadata.get(
'databases', {}
).get(name, {}),
}, ('database-{}.html'.format(to_css_class(name)), 'database.html') }, ('database-{}.html'.format(to_css_class(name)), 'database.html')
@ -686,7 +690,10 @@ class TableView(RowTableShared):
'_rows_and_columns-{}-{}.html'.format(to_css_class(name), to_css_class(table)), '_rows_and_columns-{}-{}.html'.format(to_css_class(name), to_css_class(table)),
'_rows_and_columns-table-{}-{}.html'.format(to_css_class(name), to_css_class(table)), '_rows_and_columns-table-{}-{}.html'.format(to_css_class(name), to_css_class(table)),
'_rows_and_columns.html', '_rows_and_columns.html',
] ],
'metadata': self.ds.metadata.get(
'databases', {}
).get(name, {}).get('tables', {}).get(table, {}),
} }
return { return {
@ -750,7 +757,10 @@ class RowView(RowTableShared):
'_rows_and_columns-{}-{}.html'.format(to_css_class(name), to_css_class(table)), '_rows_and_columns-{}-{}.html'.format(to_css_class(name), to_css_class(table)),
'_rows_and_columns-row-{}-{}.html'.format(to_css_class(name), to_css_class(table)), '_rows_and_columns-row-{}-{}.html'.format(to_css_class(name), to_css_class(table)),
'_rows_and_columns.html', '_rows_and_columns.html',
] ],
'metadata': self.ds.metadata.get(
'databases', {}
).get(name, {}).get('tables', {}).get(table, {}),
} }
data = { data = {

View file

@ -0,0 +1,25 @@
{% if metadata.description_html or metadata.description %}
<div class="metadata-description">
{% if metadata.description_html %}
{{ metadata.description_html|safe }}
{% else %}
{{ metadata.description }}
{% endif %}
</div>
{% endif %}
{% if metadata.license or metadata.license_url or metadata.source or metadata.source_url %}
<p>
{% if metadata.license or metadata.license_url %}Data license:
{% if metadata.license_url %}
<a href="{{ metadata.license_url }}">{{ metadata.license or metadata.license_url }}</a>
{% else %}
{{ metadata.license }}
{% endif %}
{% endif %}
{% if metadata.source or metadata.source_url %}{% if metadata.license or metadata.license_url %}&middot;{% endif %}
Data source: {% if metadata.source_url %}
<a href="{{ metadata.source_url }}">
{% endif %}{{ metadata.source or metadata.source_url }}{% if metadata.source_url %}</a>{% endif %}
{% endif %}
</p>
{% endif %}

View file

@ -20,19 +20,17 @@
<div class="ft"> <div class="ft">
Powered by <a href="https://github.com/simonw/datasette" title="Datasette v{{ datasette_version }}">Datasette</a> Powered by <a href="https://github.com/simonw/datasette" title="Datasette v{{ datasette_version }}">Datasette</a>
{% if query_ms %}&middot; Query took {{ query_ms|round(3) }}ms{% endif %} {% if query_ms %}&middot; Query took {{ query_ms|round(3) }}ms{% endif %}
{% if metadata.license %}&middot; Data license: {% if metadata.license or metadata.license_url %}&middot; Data license:
{% if metadata.license_url %} {% if metadata.license_url %}
<a href="{{ metadata.license_url }}">{{ metadata.license }}</a> <a href="{{ metadata.license_url }}">{{ metadata.license or metadata.license_url }}</a>
{% else %} {% else %}
{{ metadata.license }} {{ metadata.license }}
{% endif %} {% endif %}
{% endif %} {% endif %}
{% if metadata.source_url %}&middot; {% if metadata.source or metadata.source_url %}&middot;
{% if metadata.source %} Data source: {% if metadata.source_url %}
Data source: <a href="{{ metadata.source_url }}">{{ metadata.source }}</a> <a href="{{ metadata.source_url }}">
{% else %} {% endif %}{{ metadata.source or metadata.source_url }}{% if metadata.source_url %}</a>{% endif %}
<a href="{{ metadata.source_url }}">Data source</a>
{% endif %}
{% endif %} {% endif %}
</div> </div>

View file

@ -12,7 +12,9 @@
{% block content %} {% block content %}
<div class="hd"><a href="/">home</a></div> <div class="hd"><a href="/">home</a></div>
<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}">{{ database }}</h1> <h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}">{{ metadata.title or database }}</h1>
{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}
<form class="sql" action="/{{ database }}-{{ database_hash }}" method="get"> <form class="sql" action="/{{ database }}-{{ database_hash }}" method="get">
<h3>Custom SQL query</h3> <h3>Custom SQL query</h3>

View file

@ -6,24 +6,8 @@
{% block content %} {% block content %}
<h1>{{ metadata.title or "Datasette" }}</h1> <h1>{{ metadata.title or "Datasette" }}</h1>
{% if metadata.license or metadata.source_url %}
<p> {% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}
{% if metadata.license %}Data license:
{% if metadata.license_url %}
<a href="{{ metadata.license_url }}">{{ metadata.license }}</a>
{% else %}
{{ metadata.license }}
{% endif %}
{% endif %}
{% if metadata.source_url %}{% if metadata.license %}&middot;{% endif %}
{% if metadata.source %}
Data source: <a href="{{ metadata.source_url }}">{{ metadata.source }}</a>
{% else %}
<a href="{{ metadata.source_url }}">Data source</a>
{% endif %}
{% endif %}
</p>
{% endif %}
{% for database in databases %} {% for database in databases %}
<h2 style="padding-left: 10px; border-left: 10px solid #{{ database.hash[:6] }}"><a href="{{ database.path }}">{{ database.name }}</a></h2> <h2 style="padding-left: 10px; border-left: 10px solid #{{ database.hash[:6] }}"><a href="{{ database.path }}">{{ database.name }}</a></h2>

View file

@ -20,6 +20,8 @@
<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}">{{ table }}: {{ ', '.join(primary_key_values) }}</a></h1> <h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}">{{ table }}: {{ ', '.join(primary_key_values) }}</a></h1>
{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}
<p>This data as <a href="{{ url_json }}">.json</a>, <a href="{{ url_jsono }}">.jsono</a></p> <p>This data as <a href="{{ url_json }}">.json</a>, <a href="{{ url_jsono }}">.jsono</a></p>
{% include custom_rows_and_columns_templates %} {% include custom_rows_and_columns_templates %}

View file

@ -19,7 +19,9 @@
{% block content %} {% block content %}
<div class="hd"><a href="/">home</a> / <a href="/{{ database }}-{{ database_hash }}">{{ database }}</a></div> <div class="hd"><a href="/">home</a> / <a href="/{{ database }}-{{ database_hash }}">{{ database }}</a></div>
<h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}">{{ table }}{% if is_view %} (view){% endif %}</h1> <h1 style="padding-left: 10px; border-left: 10px solid #{{ database_hash[:6] }}">{{ metadata.title or table }}{% if is_view %} (view){% endif %}</h1>
{% block description_source_license %}{% include "_description_source_license.html" %}{% endblock %}
{% if filtered_table_rows or human_filter_description %} {% if filtered_table_rows or human_filter_description %}
<h3>{% if filtered_table_rows or filtered_table_rows == 0 %}{{ "{:,}".format(filtered_table_rows) }} row{% if filtered_table_rows == 1 %}{% else %}s{% endif %}{% endif %} <h3>{% if filtered_table_rows or filtered_table_rows == 0 %}{{ "{:,}".format(filtered_table_rows) }} row{% if filtered_table_rows == 1 %}{% else %}s{% endif %}{% endif %}