repos: 261634807
This data as json
id | node_id | name | full_name | private | owner | html_url | description | fork | created_at | updated_at | pushed_at | homepage | size | stargazers_count | watchers_count | language | has_issues | has_projects | has_downloads | has_wiki | has_pages | forks_count | archived | disabled | open_issues_count | license | topics | forks | open_issues | watchers | default_branch | permissions | temp_clone_token | organization | network_count | subscribers_count | readme | readme_html | allow_forking | visibility | is_template | template_repository | web_commit_signoff_required | has_discussions |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
261634807 | MDEwOlJlcG9zaXRvcnkyNjE2MzQ4MDc= | datasette-media | simonw/datasette-media | 0 | 9599 | https://github.com/simonw/datasette-media | Datasette plugin for serving media based on a SQL query | 0 | 2020-05-06T02:42:57Z | 2021-05-03T05:04:39Z | 2020-07-30T23:39:29Z | 70 | 11 | 11 | Python | 1 | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 8 | apache-2.0 | ["datasette", "datasette-plugin", "datasette-io"] | 0 | 8 | 11 | main | {"admin": false, "push": false, "pull": false} | 0 | 1 | # datasette-media [](https://pypi.org/project/datasette-media/) [](https://github.com/simonw/datasette-media/releases) [](https://circleci.com/gh/simonw/datasette-media) [](https://github.com/simonw/datasette-media/blob/master/LICENSE) Datasette plugin for serving media based on a SQL query. Use this when you have a database table containing references to files on disk - or binary content stored in BLOB columns - that you would like to be able to serve to your users. ## Installation Install this plugin in the same environment as Datasette. $ pip install datasette-media ### HEIC image support Modern iPhones save their photos using the [HEIC image format](https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format). Processing these images requires an additional dependency, [pyheif](https://pypi.org/project/pyheif/). You can include this dependency by running: $ pip install datasette-media[heif] ## Usage You can use this plugin to configure Datasette to serve static media based on SQL queries to an underlying database table. Media will be served from URLs that start with `/-/media/`. The full URL to each media asset will look like this: /-/media/type-of-media/media-key `type-of-media` will correspond to a configured SQL query, and might be something like `photo`. `media-key` will be an identifier that is used as part of the underlying SQL query to find which file should be served. ### Serving static files from disk The following ``metadata.json`` configuration will cause this plugin to serve files from disk, based on queries to a database table called `apple_photos`. ```json { "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key" } } } } ``` A request to `/-/media/photo/CF972D33-5324-44F2-8DAE-22CB3182CD31` will execute the following SQL query: ```sql select filepath from apple_photos where uuid=:key ``` The value from the URL - in this case `CF972D33-5324-44F2-8DAE-22CB3182CD31` - will be passed as the `:key` parameter to the query. The query returns a `filepath` value that has been read from the table. The plugin will then read that file from disk and serve it in response to the request. SQL queries default to running against the first connected database. You can specify a different database to execute the query against using `"database": "name_of_db"`. To execute against `photos.db`, use this: ```json { "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key", "database": "photos" } } } } ``` See [dogsheep-photos](https://github.com/dogsheep/dogsheep-photos) for an example of an application that can benefit from this plugin. ### Serving binary content from BLOB columns If your SQL query returns a `content` column, this will be served directly to the user: ```json { "plugins": { "datasette-media": { "photo": { "sql": "select thumbnail as content from photos where uuid=:key", "database": "thumbs" } } } } ``` You can also return a `content_type` column which will be used as the `Content-Type` header served to the user: ```json { "plugins": { "datasette-media": { "photo": { "sql": "select body as content, 'text/html;charset=utf-8' as content_type from documents where id=:key", "database": "documents" } } } } ``` If you do not specify a `content_type` the default of `application/octet-stream` will be used. ### Serving content proxied from a URL To serve content that is itself fetched from elsewhere, return a `content_url` column. This can be particularly useful when combined with the ability to resize images (described in the next section). ```json { "plugins": { "datasette-media": { "photos": { "sql": "select photo_url as content_url from photos where id=:key", "database": "photos", "enable_transform": true } } } } ``` Now you can access resized versions of images from that URL like so: /-/media/photos/13?w=200 ### Setting a download file name The `content_filename` column can be returned to force browsers to download the content using a specific file name. ```json { "plugins": { "datasette-media": { "hello": { "sql": "select 'Hello ' || :key as content, 'hello.txt' as content_filename" } } } } ``` Visiting `/-/media/hello/Groot` will cause your browser to download a file called `hello.txt` containing the text `Hello Groot`. ### Resizing or transforming images Your SQL query can specify that an image should be resized and/or converted to another format by returning additional columns. All three are optional. * `resize_width` - the width to resize the image to * `resize_width` - the height to resize the image to * `output_format` - the output format to use (e.g. `jpeg` or `png`) - any output format [supported by Pillow](https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html) is allowed here. If you specify one but not the other of `resize_width` or `resize_height` the unspecified one will be calculated automatically to maintain the aspect ratio of the image. Here's an example configuration that will resize all images to be JPEGs that are 200 pixels in height: ```json { "plugins": { "datasette-media": { "photo": { "sql": "select filepath, 200 as resize_height, 'jpeg' as output_format from apple_photos where uuid=:key", "database": "photos" } } } } ``` If you enable the `enable_transform` configuration option you can instead specify transform parameters at runtime using querystring parameters. For example: - `/-/media/photo/CF972D33?w=200` to resize to a fixed width - `/-/media/photo/CF972D33?h=200` to resize to a fixed height - `/-/media/photo/CF972D33?format=jpeg` to convert to JPEG That option is added like so: ```json { "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key", "database": "photos", "enable_transform": true } } } } ``` The maximum allowed height or width is 4000 pixels. You can change this limit using the `"max_width_height"` option: ```json { "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key", "database": "photos", "enable_transform": true, "max_width_height": 1000 } } } } ``` ## Configuration In addition to the different named content types, the following special plugin configuration setting is available: - `transform_threads` - number of threads to use for running transformations (e.g. resizing). Defaults to 4. This can be used like this: ```json { "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key", "database": "photos" }, "transform_threads": 8 } } } ``` | <div id="readme" class="md" data-path="README.md"><article class="markdown-body entry-content container-lg" itemprop="text"><h1><a id="user-content-datasette-media" class="anchor" aria-hidden="true" href="#user-content-datasette-media"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>datasette-media</h1> <p><a href="https://pypi.org/project/datasette-media/" rel="nofollow"><img src="https://camo.githubusercontent.com/e54db370ebd4d8d68a1054cdb8186da706ee7e8e725a8543b6681404e49bff00/68747470733a2f2f696d672e736869656c64732e696f2f707970692f762f6461746173657474652d6d656469612e737667" alt="PyPI" data-canonical-src="https://img.shields.io/pypi/v/datasette-media.svg" style="max-width:100%;"></a> <a href="https://github.com/simonw/datasette-media/releases"><img src="https://camo.githubusercontent.com/45b31e5abfda86f1f9f9396856b3e703513fbfd980f2070daf1fa3fcb898214b/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f762f72656c656173652f73696d6f6e772f6461746173657474652d6d656469613f696e636c7564655f70726572656c6561736573266c6162656c3d6368616e67656c6f67" alt="Changelog" data-canonical-src="https://img.shields.io/github/v/release/simonw/datasette-media?include_prereleases&label=changelog" style="max-width:100%;"></a> <a href="https://circleci.com/gh/simonw/datasette-media" rel="nofollow"><img src="https://camo.githubusercontent.com/3f836c0fc5a36c2afcce223b886456440cf30d4f4cff3c009a40c730fcc0a66d/68747470733a2f2f636972636c6563692e636f6d2f67682f73696d6f6e772f6461746173657474652d6d656469612e7376673f7374796c653d737667" alt="CircleCI" data-canonical-src="https://circleci.com/gh/simonw/datasette-media.svg?style=svg" style="max-width:100%;"></a> <a href="https://github.com/simonw/datasette-media/blob/master/LICENSE"><img src="https://camo.githubusercontent.com/1698104e976c681143eb0841f9675c6f802bb7aa832afc0c7a4e719b1f3cf955/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f6c6963656e73652d417061636865253230322e302d626c75652e737667" alt="License" data-canonical-src="https://img.shields.io/badge/license-Apache%202.0-blue.svg" style="max-width:100%;"></a></p> <p>Datasette plugin for serving media based on a SQL query.</p> <p>Use this when you have a database table containing references to files on disk - or binary content stored in BLOB columns - that you would like to be able to serve to your users.</p> <h2><a id="user-content-installation" class="anchor" aria-hidden="true" href="#user-content-installation"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Installation</h2> <p>Install this plugin in the same environment as Datasette.</p> <div class="snippet-clipboard-content position-relative" data-snippet-clipboard-copy-content="$ pip install datasette-media "><pre><code>$ pip install datasette-media </code></pre></div> <h3><a id="user-content-heic-image-support" class="anchor" aria-hidden="true" href="#user-content-heic-image-support"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>HEIC image support</h3> <p>Modern iPhones save their photos using the <a href="https://en.wikipedia.org/wiki/High_Efficiency_Image_File_Format" rel="nofollow">HEIC image format</a>. Processing these images requires an additional dependency, <a href="https://pypi.org/project/pyheif/" rel="nofollow">pyheif</a>. You can include this dependency by running:</p> <div class="snippet-clipboard-content position-relative" data-snippet-clipboard-copy-content="$ pip install datasette-media[heif] "><pre><code>$ pip install datasette-media[heif] </code></pre></div> <h2><a id="user-content-usage" class="anchor" aria-hidden="true" href="#user-content-usage"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Usage</h2> <p>You can use this plugin to configure Datasette to serve static media based on SQL queries to an underlying database table.</p> <p>Media will be served from URLs that start with <code>/-/media/</code>. The full URL to each media asset will look like this:</p> <div class="snippet-clipboard-content position-relative" data-snippet-clipboard-copy-content="/-/media/type-of-media/media-key "><pre><code>/-/media/type-of-media/media-key </code></pre></div> <p><code>type-of-media</code> will correspond to a configured SQL query, and might be something like <code>photo</code>. <code>media-key</code> will be an identifier that is used as part of the underlying SQL query to find which file should be served.</p> <h3><a id="user-content-serving-static-files-from-disk" class="anchor" aria-hidden="true" href="#user-content-serving-static-files-from-disk"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Serving static files from disk</h3> <p>The following <code>metadata.json</code> configuration will cause this plugin to serve files from disk, based on queries to a database table called <code>apple_photos</code>.</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key" } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photo<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select filepath from apple_photos where uuid=:key<span class="pl-pds">"</span></span> } } } }</pre></div> <p>A request to <code>/-/media/photo/CF972D33-5324-44F2-8DAE-22CB3182CD31</code> will execute the following SQL query:</p> <div class="highlight highlight-source-sql position-relative" data-snippet-clipboard-copy-content="select filepath from apple_photos where uuid=:key "><pre><span class="pl-k">select</span> filepath <span class="pl-k">from</span> apple_photos <span class="pl-k">where</span> uuid<span class="pl-k">=</span>:key</pre></div> <p>The value from the URL - in this case <code>CF972D33-5324-44F2-8DAE-22CB3182CD31</code> - will be passed as the <code>:key</code> parameter to the query.</p> <p>The query returns a <code>filepath</code> value that has been read from the table. The plugin will then read that file from disk and serve it in response to the request.</p> <p>SQL queries default to running against the first connected database. You can specify a different database to execute the query against using <code>"database": "name_of_db"</code>. To execute against <code>photos.db</code>, use this:</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key", "database": "photos" } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photo<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select filepath from apple_photos where uuid=:key<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>photos<span class="pl-pds">"</span></span> } } } }</pre></div> <p>See <a href="https://github.com/dogsheep/dogsheep-photos">dogsheep-photos</a> for an example of an application that can benefit from this plugin.</p> <h3><a id="user-content-serving-binary-content-from-blob-columns" class="anchor" aria-hidden="true" href="#user-content-serving-binary-content-from-blob-columns"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Serving binary content from BLOB columns</h3> <p>If your SQL query returns a <code>content</code> column, this will be served directly to the user:</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photo": { "sql": "select thumbnail as content from photos where uuid=:key", "database": "thumbs" } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photo<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select thumbnail as content from photos where uuid=:key<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>thumbs<span class="pl-pds">"</span></span> } } } }</pre></div> <p>You can also return a <code>content_type</code> column which will be used as the <code>Content-Type</code> header served to the user:</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photo": { "sql": "select body as content, 'text/html;charset=utf-8' as content_type from documents where id=:key", "database": "documents" } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photo<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select body as content, 'text/html;charset=utf-8' as content_type from documents where id=:key<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>documents<span class="pl-pds">"</span></span> } } } }</pre></div> <p>If you do not specify a <code>content_type</code> the default of <code>application/octet-stream</code> will be used.</p> <h3><a id="user-content-serving-content-proxied-from-a-url" class="anchor" aria-hidden="true" href="#user-content-serving-content-proxied-from-a-url"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Serving content proxied from a URL</h3> <p>To serve content that is itself fetched from elsewhere, return a <code>content_url</code> column. This can be particularly useful when combined with the ability to resize images (described in the next section).</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photos": { "sql": "select photo_url as content_url from photos where id=:key", "database": "photos", "enable_transform": true } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photos<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select photo_url as content_url from photos where id=:key<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>photos<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>enable_transform<span class="pl-pds">"</span></span>: <span class="pl-c1">true</span> } } } }</pre></div> <p>Now you can access resized versions of images from that URL like so:</p> <div class="snippet-clipboard-content position-relative" data-snippet-clipboard-copy-content="/-/media/photos/13?w=200 "><pre><code>/-/media/photos/13?w=200 </code></pre></div> <h3><a id="user-content-setting-a-download-file-name" class="anchor" aria-hidden="true" href="#user-content-setting-a-download-file-name"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Setting a download file name</h3> <p>The <code>content_filename</code> column can be returned to force browsers to download the content using a specific file name.</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "hello": { "sql": "select 'Hello ' || :key as content, 'hello.txt' as content_filename" } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>hello<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select 'Hello ' || :key as content, 'hello.txt' as content_filename<span class="pl-pds">"</span></span> } } } }</pre></div> <p>Visiting <code>/-/media/hello/Groot</code> will cause your browser to download a file called <code>hello.txt</code> containing the text <code>Hello Groot</code>.</p> <h3><a id="user-content-resizing-or-transforming-images" class="anchor" aria-hidden="true" href="#user-content-resizing-or-transforming-images"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Resizing or transforming images</h3> <p>Your SQL query can specify that an image should be resized and/or converted to another format by returning additional columns. All three are optional.</p> <ul> <li><code>resize_width</code> - the width to resize the image to</li> <li><code>resize_width</code> - the height to resize the image to</li> <li><code>output_format</code> - the output format to use (e.g. <code>jpeg</code> or <code>png</code>) - any output format <a href="https://pillow.readthedocs.io/en/stable/handbook/image-file-formats.html" rel="nofollow">supported by Pillow</a> is allowed here.</li> </ul> <p>If you specify one but not the other of <code>resize_width</code> or <code>resize_height</code> the unspecified one will be calculated automatically to maintain the aspect ratio of the image.</p> <p>Here's an example configuration that will resize all images to be JPEGs that are 200 pixels in height:</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photo": { "sql": "select filepath, 200 as resize_height, 'jpeg' as output_format from apple_photos where uuid=:key", "database": "photos" } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photo<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select filepath, 200 as resize_height, 'jpeg' as output_format from apple_photos where uuid=:key<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>photos<span class="pl-pds">"</span></span> } } } }</pre></div> <p>If you enable the <code>enable_transform</code> configuration option you can instead specify transform parameters at runtime using querystring parameters. For example:</p> <ul> <li><code>/-/media/photo/CF972D33?w=200</code> to resize to a fixed width</li> <li><code>/-/media/photo/CF972D33?h=200</code> to resize to a fixed height</li> <li><code>/-/media/photo/CF972D33?format=jpeg</code> to convert to JPEG</li> </ul> <p>That option is added like so:</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key", "database": "photos", "enable_transform": true } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photo<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select filepath from apple_photos where uuid=:key<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>photos<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>enable_transform<span class="pl-pds">"</span></span>: <span class="pl-c1">true</span> } } } }</pre></div> <p>The maximum allowed height or width is 4000 pixels. You can change this limit using the <code>"max_width_height"</code> option:</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key", "database": "photos", "enable_transform": true, "max_width_height": 1000 } } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photo<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select filepath from apple_photos where uuid=:key<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>photos<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>enable_transform<span class="pl-pds">"</span></span>: <span class="pl-c1">true</span>, <span class="pl-s"><span class="pl-pds">"</span>max_width_height<span class="pl-pds">"</span></span>: <span class="pl-c1">1000</span> } } } }</pre></div> <h2><a id="user-content-configuration" class="anchor" aria-hidden="true" href="#user-content-configuration"><svg class="octicon octicon-link" viewBox="0 0 16 16" version="1.1" width="16" height="16" aria-hidden="true"><path fill-rule="evenodd" d="M7.775 3.275a.75.75 0 001.06 1.06l1.25-1.25a2 2 0 112.83 2.83l-2.5 2.5a2 2 0 01-2.83 0 .75.75 0 00-1.06 1.06 3.5 3.5 0 004.95 0l2.5-2.5a3.5 3.5 0 00-4.95-4.95l-1.25 1.25zm-4.69 9.64a2 2 0 010-2.83l2.5-2.5a2 2 0 012.83 0 .75.75 0 001.06-1.06 3.5 3.5 0 00-4.95 0l-2.5 2.5a3.5 3.5 0 004.95 4.95l1.25-1.25a.75.75 0 00-1.06-1.06l-1.25 1.25a2 2 0 01-2.83 0z"></path></svg></a>Configuration</h2> <p>In addition to the different named content types, the following special plugin configuration setting is available:</p> <ul> <li><code>transform_threads</code> - number of threads to use for running transformations (e.g. resizing). Defaults to 4.</li> </ul> <p>This can be used like this:</p> <div class="highlight highlight-source-json position-relative" data-snippet-clipboard-copy-content="{ "plugins": { "datasette-media": { "photo": { "sql": "select filepath from apple_photos where uuid=:key", "database": "photos" }, "transform_threads": 8 } } } "><pre>{ <span class="pl-s"><span class="pl-pds">"</span>plugins<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>datasette-media<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>photo<span class="pl-pds">"</span></span>: { <span class="pl-s"><span class="pl-pds">"</span>sql<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>select filepath from apple_photos where uuid=:key<span class="pl-pds">"</span></span>, <span class="pl-s"><span class="pl-pds">"</span>database<span class="pl-pds">"</span></span>: <span class="pl-s"><span class="pl-pds">"</span>photos<span class="pl-pds">"</span></span> }, <span class="pl-s"><span class="pl-pds">"</span>transform_threads<span class="pl-pds">"</span></span>: <span class="pl-c1">8</span> } } }</pre></div> </article></div> |
Links from other tables
- 6 rows from repo in releases