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 135007287,MDEwOlJlcG9zaXRvcnkxMzUwMDcyODc=,datasette-leaflet-geojson,simonw/datasette-leaflet-geojson,0,9599,https://github.com/simonw/datasette-leaflet-geojson,Datasette plugin that replaces any GeoJSON column values with a Leaflet map.,0,2018-05-27T01:42:30Z,2022-08-26T23:27:11Z,2022-08-26T23:27:08Z,,91,9,9,Python,1,1,1,1,0,4,0,0,3,,"[""datasette"", ""datasette-io"", ""datasette-plugin"", ""gis"", ""leaflet""]",4,3,9,main,"{""admin"": false, ""maintain"": false, ""push"": false, ""triage"": false, ""pull"": false}",,,4,2,"# datasette-leaflet-geojson [![PyPI](https://img.shields.io/pypi/v/datasette-leaflet-geojson.svg)](https://pypi.org/project/datasette-leaflet-geojson/) [![Changelog](https://img.shields.io/github/v/release/simonw/datasette-leaflet-geojson?include_prereleases&label=changelog)](https://github.com/simonw/datasette-leaflet-geojson/releases) [![Tests](https://github.com/simonw/datasette-leaflet-geojson/workflows/Test/badge.svg)](https://github.com/simonw/datasette-leaflet-geojson/actions?query=workflow%3ATest) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/simonw/datasette-leaflet-geojson/blob/main/LICENSE) Datasette plugin that replaces any GeoJSON column values with a Leaflet map ## Installation Install this plugin in the same environment as Datasette. $ datasette install datasette-leaflet-geojson ## Usage Any columns containing valid GeoJSON strings will have their contents replaced with a Leaflet map when they are displayed in the Datasette interface. ## Demo You can try this plugin out at https://calands.datasettes.com/calands/superunits_with_maps ![datasette-leaflet-geojson in action](https://raw.github.com/simonw/datasette-leaflet-geojson/main/datasette-leaflet-geojson.png) ## Configuration By default this plugin displays maps for the first ten rows, and shows a ""Click to load map"" prompt for rows past the first ten. You can change this limit using the `default_maps_to_load` plugin configuration setting. Add this to your `metadata.json`: ```json { ""plugins"": { ""datasette-leaflet-geojson"": { ""default_maps_to_load"": 20 } } } ``` Then run Datasette with `datasette mydb.db -m metadata.json`. ","

datasette-leaflet-geojson

Datasette plugin that replaces any GeoJSON column values with a Leaflet map

Installation

Install this plugin in the same environment as Datasette.

$ datasette install datasette-leaflet-geojson

Usage

Any columns containing valid GeoJSON strings will have their contents replaced with a Leaflet map when they are displayed in the Datasette interface.

Demo

You can try this plugin out at https://calands.datasettes.com/calands/superunits_with_maps

Configuration

By default this plugin displays maps for the first ten rows, and shows a ""Click to load map"" prompt for rows past the first ten.

You can change this limit using the default_maps_to_load plugin configuration setting. Add this to your metadata.json:

{
    ""plugins"": {
        ""datasette-leaflet-geojson"": {
            ""default_maps_to_load"": 20
        }
    }
}

Then run Datasette with datasette mydb.db -m metadata.json.

",1,public,0,,0, 234825790,MDEwOlJlcG9zaXRvcnkyMzQ4MjU3OTA=,datasette-upload-csvs,simonw/datasette-upload-csvs,0,9599,https://github.com/simonw/datasette-upload-csvs,Datasette plugin for uploading CSV files and converting them to database tables,0,2020-01-19T02:07:05Z,2022-07-03T20:58:20Z,2022-09-09T16:23:59Z,https://datasette.io/plugins/datasette-upload-csvs,58,9,9,Python,1,1,1,1,0,1,0,0,4,apache-2.0,"[""csvs"", ""datasette"", ""datasette-io"", ""datasette-plugin""]",1,4,9,main,"{""admin"": false, ""maintain"": false, ""push"": false, ""triage"": false, ""pull"": false}",,,1,2,"# datasette-upload-csvs [![PyPI](https://img.shields.io/pypi/v/datasette-upload-csvs.svg)](https://pypi.org/project/datasette-upload-csvs/) [![Changelog](https://img.shields.io/github/v/release/simonw/datasette-upload-csvs?include_prereleases&label=changelog)](https://github.com/simonw/datasette-upload-csvs/releases) [![Tests](https://github.com/simonw/datasette-upload-csvs/workflows/Test/badge.svg)](https://github.com/simonw/datasette-upload-csvs/actions?query=workflow%3ATest) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/simonw/datasette-upload-csvs/blob/main/LICENSE) Datasette plugin for uploading CSV files and converting them to database tables ## Installation datasette install datasette-upload-csvs ## Usage The plugin adds an interface at `/-/upload-csvs` for uploading a CSV file and using it to create a new database table. By default only [the root actor](https://datasette.readthedocs.io/en/stable/authentication.html#using-the-root-actor) can access the page - so you'll need to run Datasette with the `--root` option and click on the link shown in the terminal to sign in and access the page. The `upload-csvs` permission governs access. You can use permission plugins such as [datasette-permissions-sql](https://github.com/simonw/datasette-permissions-sql) to grant additional access to the write interface. ","

datasette-upload-csvs

Datasette plugin for uploading CSV files and converting them to database tables

Installation

datasette install datasette-upload-csvs

Usage

The plugin adds an interface at /-/upload-csvs for uploading a CSV file and using it to create a new database table.

By default only the root actor can access the page - so you'll need to run Datasette with the --root option and click on the link shown in the terminal to sign in and access the page.

The upload-csvs permission governs access. You can use permission plugins such as datasette-permissions-sql to grant additional access to the write interface.

",1,public,0,,0, 280500027,MDEwOlJlcG9zaXRvcnkyODA1MDAwMjc=,datasette-insert,simonw/datasette-insert,0,9599,https://github.com/simonw/datasette-insert,Datasette plugin for inserting and updating data,0,2020-07-17T18:40:34Z,2022-06-27T02:54:14Z,2022-07-22T17:52:23Z,,54,9,9,Python,1,1,1,1,0,0,0,0,1,,"[""datasette"", ""datasette-io"", ""datasette-plugin""]",0,1,9,main,"{""admin"": false, ""maintain"": false, ""push"": false, ""triage"": false, ""pull"": false}",,,0,2,"# datasette-insert [![PyPI](https://img.shields.io/pypi/v/datasette-insert.svg)](https://pypi.org/project/datasette-insert/) [![Changelog](https://img.shields.io/github/v/release/simonw/datasette-insert?include_prereleases&label=changelog)](https://github.com/simonw/datasette-insert/releases) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/simonw/datasette-insert/blob/master/LICENSE) Datasette plugin for inserting and updating data ## Installation Install this plugin in the same environment as Datasette. $ pip install datasette-insert This plugin should always be deployed with additional configuration to prevent unauthenticated access, see notes below. If you are trying it out on your own local machine, you can `pip install` the [datasette-insert-unsafe](https://github.com/simonw/datasette-insert-unsafe) plugin to allow access without needing to set up authentication or permissions separately. ## Inserting data and creating tables Start datasette and make sure it has a writable SQLite database attached to it. If you have not yet created a database file you can use this: datasette data.db --create The `--create` option will create a new empty `data.db` database file if it does not already exist. The plugin adds an endpoint that allows data to be inserted or updated and tables to be created by POSTing JSON data to the following URL: /-/insert/name-of-database/name-of-table The JSON should look like this: ```json [ { ""id"": 1, ""name"": ""Cleopaws"", ""age"": 5 }, { ""id"": 2, ""name"": ""Pancakes"", ""age"": 5 } ] ``` The first time data is posted to the URL a table of that name will be created if it does not aready exist, with the desired columns. You can specify which column should be used as the primary key using the `?pk=` URL argument. Here's how to POST to a database and create a new table using the Python `requests` library: ```python import requests requests.post(""http://localhost:8001/-/insert/data/dogs?pk=id"", json=[ { ""id"": 1, ""name"": ""Cleopaws"", ""age"": 5 }, { ""id"": 2, ""name"": ""Pancakes"", ""age"": 4 } ]) ``` And here's how to do the same thing using `curl`: ``` curl --request POST \ --data '[ { ""id"": 1, ""name"": ""Cleopaws"", ""age"": 5 }, { ""id"": 2, ""name"": ""Pancakes"", ""age"": 4 } ]' \ 'http://localhost:8001/-/insert/data/dogs?pk=id' ``` Or by piping in JSON like so: cat dogs.json | curl --request POST -d @- \ 'http://localhost:8001/-/insert/data/dogs?pk=id' ### Inserting a single row If you are inserting a single row you can optionally send it as a dictionary rather than a list with a single item: ``` curl --request POST \ --data '{ ""id"": 1, ""name"": ""Cleopaws"", ""age"": 5 }' \ 'http://localhost:8001/-/insert/data/dogs?pk=id' ``` ### Automatically adding new columns If you send data to an existing table with keys that are not reflected by the existing columns, you will get an HTTP 400 error with a JSON response like this: ```json { ""status"": 400, ""error"": ""Unknown keys: 'foo'"", ""error_code"": ""unknown_keys"" } ``` If you add `?alter=1` to the URL you are posting to any missing columns will be automatically added: ``` curl --request POST \ --data '[ { ""id"": 3, ""name"": ""Boris"", ""age"": 1, ""breed"": ""Husky"" } ]' \ 'http://localhost:8001/-/insert/data/dogs?alter=1' ``` ## Upserting data An ""upsert"" operation can be used to partially update a record. With upserts you can send a subset of the keys and, if the ID matches the specified primary key, they will be used to update an existing record. Upserts can be sent to the `/-/upsert` API endpoint. This example will update the dog with ID=1's age from 5 to 7: ``` curl --request POST \ --data '{ ""id"": 1, ""age"": 7 }' \ 'http://localhost:3322/-/upsert/data/dogs?pk=id' ``` Like the `/-/insert` endpoint, the `/-/upsert` endpoint can accept an array of objects too. It also supports the `?alter=1` option. ## Permissions and authentication This plugin defaults to denying all access, to help ensure people don't accidentally deploy it on the open internet in an unsafe configuration. You can read about [Datasette's approach to authentication](https://datasette.readthedocs.io/en/stable/authentication.html) in the Datasette manual. You can install the `datasette-insert-unsafe` plugin to run in unsafe mode, where all access is allowed by default. I recommend using this plugin in conjunction with [datasette-auth-tokens](https://github.com/simonw/datasette-auth-tokens), which provides a mechanism for making authenticated calls using API tokens. You can then use [""allow"" blocks](https://datasette.readthedocs.io/en/stable/authentication.html#defining-permissions-with-allow-blocks) in the `datasette-insert` plugin configuration to specify which authenticated tokens are allowed to make use of the API. Here's an example `metadata.json` file which restricts access to the `/-/insert` API to an API token defined in an `INSERT_TOKEN` environment variable: ```json { ""plugins"": { ""datasette-insert"": { ""allow"": { ""bot"": ""insert-bot"" } }, ""datasette-auth-tokens"": { ""tokens"": [ { ""token"": { ""$env"": ""INSERT_TOKEN"" }, ""actor"": { ""bot"": ""insert-bot"" } } ] } } } ``` With this configuration in place you can start Datasette like this: INSERT_TOKEN=abc123 datasette data.db -m metadata.json You can now send data to the API using `curl` like this: ``` curl --request POST \ -H ""Authorization: Bearer abc123"" \ --data '[ { ""id"": 3, ""name"": ""Boris"", ""age"": 1, ""breed"": ""Husky"" } ]' \ 'http://localhost:8001/-/insert/data/dogs' ``` Or using the Python `requests` library like so: ```python requests.post( ""http://localhost:8001/-/insert/data/dogs"", json={""id"": 1, ""name"": ""Cleopaws"", ""age"": 5}, headers={""Authorization"": ""bearer abc123""}, ) ``` ### Finely grained permissions Using an `""allow""` block as described above grants full permission to the features enabled by the API. The API implements several new Datasett permissions, which other plugins can use to make more finely grained decisions. The full set of permissions are as follows: - `insert:all` - all permissions - this is used by the `""allow""` block described above. Argument: `database_name` - `insert:insert-update` - the ability to insert data into an existing table, or to update data by its primary key. Arguments: `(database_name, table_name)` - `insert:create-table` - the ability to create a new table. Argument: `database_name` - `insert:alter-table` - the ability to add columns to an existing table (using `?alter=1`). Arguments: `(database_name, table_name)` You can use plugins like [datasette-permissions-sql](https://github.com/simonw/datasette-permissions-sql) to hook into these more detailed permissions for finely grained control over what actions each authenticated actor can take. Plugins that implement the [permission_allowed()](https://datasette.readthedocs.io/en/stable/plugin_hooks.html#plugin-hook-permission-allowed) plugin hook can take full control over these permission decisions. ## CORS If you start Datasette with the `datasette --cors` option the following HTTP headers will be added to resources served by this plugin: Access-Control-Allow-Origin: * Access-Control-Allow-Headers: content-type,authorization Access-Control-Allow-Methods: POST ## Development To set up this plugin locally, first checkout the code. Then create a new virtual environment: cd datasette-insert python3 -m venv venv source venv/bin/activate Now install the dependencies and tests: pip install -e '.[test]' To run the tests: pytest ","

datasette-insert

Datasette plugin for inserting and updating data

Installation

Install this plugin in the same environment as Datasette.

$ pip install datasette-insert

This plugin should always be deployed with additional configuration to prevent unauthenticated access, see notes below.

If you are trying it out on your own local machine, you can pip install the datasette-insert-unsafe plugin to allow access without needing to set up authentication or permissions separately.

Inserting data and creating tables

Start datasette and make sure it has a writable SQLite database attached to it. If you have not yet created a database file you can use this:

datasette data.db --create

The --create option will create a new empty data.db database file if it does not already exist.

The plugin adds an endpoint that allows data to be inserted or updated and tables to be created by POSTing JSON data to the following URL:

/-/insert/name-of-database/name-of-table

The JSON should look like this:

[
    {
        ""id"": 1,
        ""name"": ""Cleopaws"",
        ""age"": 5
    },
    {
        ""id"": 2,
        ""name"": ""Pancakes"",
        ""age"": 5
    }
]

The first time data is posted to the URL a table of that name will be created if it does not aready exist, with the desired columns.

You can specify which column should be used as the primary key using the ?pk= URL argument.

Here's how to POST to a database and create a new table using the Python requests library:

import requests

requests.post(""http://localhost:8001/-/insert/data/dogs?pk=id"", json=[
    {
        ""id"": 1,
        ""name"": ""Cleopaws"",
        ""age"": 5
    },
    {
        ""id"": 2,
        ""name"": ""Pancakes"",
        ""age"": 4
    }
])

And here's how to do the same thing using curl:

curl --request POST \
  --data '[
      {
        ""id"": 1,
        ""name"": ""Cleopaws"",
        ""age"": 5
      },
      {
        ""id"": 2,
        ""name"": ""Pancakes"",
        ""age"": 4
      }
    ]' \
    'http://localhost:8001/-/insert/data/dogs?pk=id'

Or by piping in JSON like so:

cat dogs.json | curl --request POST -d @- \
    'http://localhost:8001/-/insert/data/dogs?pk=id'

Inserting a single row

If you are inserting a single row you can optionally send it as a dictionary rather than a list with a single item:

curl --request POST \
  --data '{
      ""id"": 1,
      ""name"": ""Cleopaws"",
      ""age"": 5
    }' \
    'http://localhost:8001/-/insert/data/dogs?pk=id'

Automatically adding new columns

If you send data to an existing table with keys that are not reflected by the existing columns, you will get an HTTP 400 error with a JSON response like this:

{
    ""status"": 400,
    ""error"": ""Unknown keys: 'foo'"",
    ""error_code"": ""unknown_keys""
}

If you add ?alter=1 to the URL you are posting to any missing columns will be automatically added:

curl --request POST \
  --data '[
      {
        ""id"": 3,
        ""name"": ""Boris"",
        ""age"": 1,
        ""breed"": ""Husky""
      }
    ]' \
    'http://localhost:8001/-/insert/data/dogs?alter=1'

Upserting data

An ""upsert"" operation can be used to partially update a record. With upserts you can send a subset of the keys and, if the ID matches the specified primary key, they will be used to update an existing record.

Upserts can be sent to the /-/upsert API endpoint.

This example will update the dog with ID=1's age from 5 to 7:

curl --request POST \
  --data '{
      ""id"": 1,
      ""age"": 7
    }' \
    'http://localhost:3322/-/upsert/data/dogs?pk=id'

Like the /-/insert endpoint, the /-/upsert endpoint can accept an array of objects too. It also supports the ?alter=1 option.

Permissions and authentication

This plugin defaults to denying all access, to help ensure people don't accidentally deploy it on the open internet in an unsafe configuration.

You can read about Datasette's approach to authentication in the Datasette manual.

You can install the datasette-insert-unsafe plugin to run in unsafe mode, where all access is allowed by default.

I recommend using this plugin in conjunction with datasette-auth-tokens, which provides a mechanism for making authenticated calls using API tokens.

You can then use ""allow"" blocks in the datasette-insert plugin configuration to specify which authenticated tokens are allowed to make use of the API.

Here's an example metadata.json file which restricts access to the /-/insert API to an API token defined in an INSERT_TOKEN environment variable:

{
    ""plugins"": {
        ""datasette-insert"": {
            ""allow"": {
                ""bot"": ""insert-bot""
            }
        },
        ""datasette-auth-tokens"": {
            ""tokens"": [
                {
                    ""token"": {
                        ""$env"": ""INSERT_TOKEN""
                    },
                    ""actor"": {
                        ""bot"": ""insert-bot""
                    }
                }
            ]
        }
    }
}

With this configuration in place you can start Datasette like this:

INSERT_TOKEN=abc123 datasette data.db -m metadata.json

You can now send data to the API using curl like this:

curl --request POST \
  -H ""Authorization: Bearer abc123"" \
  --data '[
      {
        ""id"": 3,
        ""name"": ""Boris"",
        ""age"": 1,
        ""breed"": ""Husky""
      }
    ]' \
    'http://localhost:8001/-/insert/data/dogs'

Or using the Python requests library like so:

requests.post(
    ""http://localhost:8001/-/insert/data/dogs"",
    json={""id"": 1, ""name"": ""Cleopaws"", ""age"": 5},
    headers={""Authorization"": ""bearer abc123""},
)

Finely grained permissions

Using an ""allow"" block as described above grants full permission to the features enabled by the API.

The API implements several new Datasett permissions, which other plugins can use to make more finely grained decisions.

The full set of permissions are as follows:

You can use plugins like datasette-permissions-sql to hook into these more detailed permissions for finely grained control over what actions each authenticated actor can take.

Plugins that implement the permission_allowed() plugin hook can take full control over these permission decisions.

CORS

If you start Datasette with the datasette --cors option the following HTTP headers will be added to resources served by this plugin:

Access-Control-Allow-Origin: *
Access-Control-Allow-Headers: content-type,authorization
Access-Control-Allow-Methods: POST

Development

To set up this plugin locally, first checkout the code. Then create a new virtual environment:

cd datasette-insert
python3 -m venv venv
source venv/bin/activate

Now install the dependencies and tests:

pip install -e '.[test]'

To run the tests:

pytest
",1,public,0,,0, 331151708,MDEwOlJlcG9zaXRvcnkzMzExNTE3MDg=,datasette-leaflet-freedraw,simonw/datasette-leaflet-freedraw,0,9599,https://github.com/simonw/datasette-leaflet-freedraw,Draw polygons on maps in Datasette,0,2021-01-20T00:55:03Z,2021-12-17T22:07:50Z,2022-02-03T20:24:37Z,,1177,9,9,Python,1,1,1,1,0,2,0,0,2,,"[""datasette"", ""datasette-io"", ""datasette-plugin"", ""leafletjs""]",2,2,9,main,"{""admin"": false, ""maintain"": false, ""push"": false, ""triage"": false, ""pull"": false}",,,2,2,"# datasette-leaflet-freedraw [![PyPI](https://img.shields.io/pypi/v/datasette-leaflet-freedraw.svg)](https://pypi.org/project/datasette-leaflet-freedraw/) [![Changelog](https://img.shields.io/github/v/release/simonw/datasette-leaflet-freedraw?include_prereleases&label=changelog)](https://github.com/simonw/datasette-leaflet-freedraw/releases) [![Tests](https://github.com/simonw/datasette-leaflet-freedraw/workflows/Test/badge.svg)](https://github.com/simonw/datasette-leaflet-freedraw/actions?query=workflow%3ATest) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/simonw/datasette-leaflet-freedraw/blob/main/LICENSE) Draw polygons on maps in Datasette Project background: [Drawing shapes on a map to query a SpatiaLite database](https://simonwillison.net/2021/Jan/24/drawing-shapes-spatialite/). ## Installation Install this plugin in the same environment as Datasette. $ datasette install datasette-leaflet-freedraw ## Usage If a table has a SpatiaLite `geometry` column, the plugin will add a map interface to the table page allowing users to draw a shape on the map to find rows with a geometry that intersects that shape. The plugin can also work with arbitrary SQL queries. There it looks for input fields with a name of `freedraw` or that ends in `_freedraw` and replaces them with a map interface. The map interface uses the [FreeDraw](https://freedraw.herokuapp.com/) Leaflet plugin. ## Demo You can try out this plugin to run searches against the GreenInfo Network California Protected Areas Database. Here's [an example query](https://calands.datasettes.com/calands?sql=select%0D%0A++AsGeoJSON%28geometry%29%2C+*%0D%0Afrom%0D%0A++CPAD_2020a_SuperUnits%0D%0Awhere%0D%0A++PARK_NAME+like+%27%25mini%25%27+and%0D%0A++Intersects%28GeomFromGeoJSON%28%3Afreedraw%29%2C+geometry%29+%3D+1%0D%0A++and+CPAD_2020a_SuperUnits.rowid+in+%28%0D%0A++++select%0D%0A++++++rowid%0D%0A++++from%0D%0A++++++SpatialIndex%0D%0A++++where%0D%0A++++++f_table_name+%3D+%27CPAD_2020a_SuperUnits%27%0D%0A++++++and+search_frame+%3D+GeomFromGeoJSON%28%3Afreedraw%29%0D%0A++%29&freedraw=%7B%22type%22%3A%22MultiPolygon%22%2C%22coordinates%22%3A%5B%5B%5B%5B-122.42202758789064%2C37.82280243352759%5D%2C%5B-122.39868164062501%2C37.823887203271454%5D%2C%5B-122.38220214843751%2C37.81846319511331%5D%2C%5B-122.35061645507814%2C37.77071473849611%5D%2C%5B-122.34924316406251%2C37.74465712069939%5D%2C%5B-122.37258911132814%2C37.703380457832374%5D%2C%5B-122.39044189453125%2C37.690340943717715%5D%2C%5B-122.41241455078126%2C37.680559803205135%5D%2C%5B-122.44262695312501%2C37.67295135774715%5D%2C%5B-122.47283935546876%2C37.67295135774715%5D%2C%5B-122.52502441406251%2C37.68382032669382%5D%2C%5B-122.53463745117189%2C37.6892542140253%5D%2C%5B-122.54699707031251%2C37.690340943717715%5D%2C%5B-122.55798339843751%2C37.72945260537781%5D%2C%5B-122.54287719726564%2C37.77831314799672%5D%2C%5B-122.49893188476564%2C37.81303878836991%5D%2C%5B-122.46185302734376%2C37.82822612280363%5D%2C%5B-122.42889404296876%2C37.82822612280363%5D%2C%5B-122.42202758789064%2C37.82280243352759%5D%5D%5D%5D%7D) showing mini parks in San Francisco: ```sql select AsGeoJSON(geometry), * from CPAD_2020a_SuperUnits where PARK_NAME like '%mini%' and Intersects(GeomFromGeoJSON(:freedraw), geometry) = 1 and CPAD_2020a_SuperUnits.rowid in ( select rowid from SpatialIndex where f_table_name = 'CPAD_2020a_SuperUnits' and search_frame = GeomFromGeoJSON(:freedraw) ) ``` ![Screenshot of the plugin in action](https://static.simonwillison.net/static/2021/datasette-leaflet-freedraw.png) ## Development To set up this plugin locally, first checkout the code. Then create a new virtual environment: cd datasette-leaflet-freedraw python3 -mvenv venv source venv/bin/activate Or if you are using `pipenv`: pipenv shell Now install the dependencies and tests: pip install -e '.[test]' To run the tests: pytest ","

datasette-leaflet-freedraw

Draw polygons on maps in Datasette

Project background: Drawing shapes on a map to query a SpatiaLite database.

Installation

Install this plugin in the same environment as Datasette.

$ datasette install datasette-leaflet-freedraw

Usage

If a table has a SpatiaLite geometry column, the plugin will add a map interface to the table page allowing users to draw a shape on the map to find rows with a geometry that intersects that shape.

The plugin can also work with arbitrary SQL queries. There it looks for input fields with a name of freedraw or that ends in _freedraw and replaces them with a map interface.

The map interface uses the FreeDraw Leaflet plugin.

Demo

You can try out this plugin to run searches against the GreenInfo Network California Protected Areas Database. Here's an example query showing mini parks in San Francisco:

select
  AsGeoJSON(geometry), *
from
  CPAD_2020a_SuperUnits
where
  PARK_NAME like '%mini%' and
  Intersects(GeomFromGeoJSON(:freedraw), geometry) = 1
  and CPAD_2020a_SuperUnits.rowid in (
    select
      rowid
    from
      SpatialIndex
    where
      f_table_name = 'CPAD_2020a_SuperUnits'
      and search_frame = GeomFromGeoJSON(:freedraw)
  )

Development

To set up this plugin locally, first checkout the code. Then create a new virtual environment:

cd datasette-leaflet-freedraw
python3 -mvenv venv
source venv/bin/activate

Or if you are using pipenv:

pipenv shell

Now install the dependencies and tests:

pip install -e '.[test]'

To run the tests:

pytest
",1,public,0,,, 382986564,MDEwOlJlcG9zaXRvcnkzODI5ODY1NjQ=,datasette-geojson-map,eyeseast/datasette-geojson-map,0,25778,https://github.com/eyeseast/datasette-geojson-map,Render a map for any query with a geometry column,0,2021-07-05T01:54:13Z,2022-03-04T00:16:17Z,2022-04-27T20:39:47Z,,3651,9,9,Python,1,1,1,1,0,0,0,0,10,,"[""datasette-io"", ""datasette-plugin"", ""geojson"", ""gis"", ""leafletjs"", ""mapping""]",0,10,9,main,"{""admin"": false, ""maintain"": false, ""push"": false, ""triage"": false, ""pull"": false}",,,0,1,"# datasette-geojson-map [![PyPI](https://img.shields.io/pypi/v/datasette-geojson-map.svg)](https://pypi.org/project/datasette-geojson-map/) [![Changelog](https://img.shields.io/github/v/release/eyeseast/datasette-geojson-map?include_prereleases&label=changelog)](https://github.com/eyeseast/datasette-geojson-map/releases) [![Tests](https://github.com/eyeseast/datasette-geojson-map/workflows/Test/badge.svg)](https://github.com/eyeseast/datasette-geojson-map/actions?query=workflow%3ATest) [![License](https://img.shields.io/badge/license-Apache%202.0-blue.svg)](https://github.com/eyeseast/datasette-geojson-map/blob/main/LICENSE) Render a map for any query with a geometry column ## Installation Install this plugin in the same environment as Datasette. $ datasette install datasette-geojson-map ## Usage Start by loading a GIS file. For example, you might use [geojson-to-sqlite](https://pypi.org/project/geojson-to-sqlite/) or [shapefile-to-sqlite](https://pypi.org/project/shapefile-to-sqlite/) to load [neighborhood boundaries](https://bostonopendata-boston.opendata.arcgis.com/datasets/3525b0ee6e6b427f9aab5d0a1d0a1a28_0/explore) into a SQLite database. ```sh wget -O neighborhoods.geojson https://opendata.arcgis.com/datasets/3525b0ee6e6b427f9aab5d0a1d0a1a28_0.geojson geojson-to-sqlite boston.db neighborhoods neighborhoods.geojson ``` (The command above uses Spatialite, but that's not required.) Start up `datasette` and navigate to the `neighborhoods` table. ```sh datasette serve boston.db # in another terminal tab open http://localhost:8001/boston/neighborhoods ``` You should see a map centered on Boston with each neighborhood outlined. Clicking a boundary will bring up a popup with details on that feature. ![Boston neighbhorhoods map](img/boston-neighborhoods-map.png) This plugin relies on (and will install) [datasette-geojson](https://github.com/eyeseast/datasette-geojson). Any query that includes a `geometry` column will produce a map of the results. This also includes single row views. Run the included `demo` project to see it live. ## Configuration This project uses the same map configuration as [datasette-cluster-map](https://github.com/simonw/datasette-cluster-map). Here's how you would use [Stamen's terrain tiles](http://maps.stamen.com/terrain/#12/37.7706/-122.3782): ```yaml plugins: datasette-geojson-map: tile_layer: https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}.{ext} tile_layer_options: attribution: >- Map tiles by Stamen Design, under CC BY 3.0. Data by OpenStreetMap, under ODbL. subdomains: abcd minZoom: 1 maxZoom: 16 ext: jpg ``` Options: - `tile_layer`: Use a URL template that can be passed to a [Leaflet Tilelayer](https://leafletjs.com/reference-1.7.1.html#tilelayer) - `tile_layer_options`: All options will be passed to the tile layer. See [Leaflet documentation](https://leafletjs.com/reference-1.7.1.html#tilelayer) for more on possible values here. ## Styling map features Map features can be styled using the [simplestyle-spec](https://github.com/mapbox/simplestyle-spec). This requires setting specific fields on returned rows. Here's an example: ```sql SELECT Name, geometry, ""#ff0000"" as fill, ""#0000ff"" as stroke, 0.2 as stroke-width, from neighborhoods ``` That will render a neighborhood map where each polygon is filled in red, outlined in blue and lines are 0.2 pixels wide. A more useful approach would use the `CASE` statement to color features based on data: ```sql SELECT Name, geometry, CASE Name WHEN ""Roslindale"" THEN ""#ff0000"" WHEN ""Dorchester"" THEN ""#0000ff"" ELSE ""#dddddd"" END fill FROM neighborhoods ``` This will fill Roslindale in red, Dorchester in blue and all other neighborhoods in gray. ## Development To set up this plugin locally, first checkout the code. Then create a new virtual environment: cd datasette-geojson-map python3 -mvenv venv source venv/bin/activate Or if you are using `pipenv`: pipenv shell Now install the dependencies and test dependencies: pip install -e '.[test]' To run the tests: pytest ","

datasette-geojson-map

Render a map for any query with a geometry column

Installation

Install this plugin in the same environment as Datasette.

$ datasette install datasette-geojson-map

Usage

Start by loading a GIS file.

For example, you might use geojson-to-sqlite or shapefile-to-sqlite to load neighborhood boundaries into a SQLite database.

wget -O neighborhoods.geojson https://opendata.arcgis.com/datasets/3525b0ee6e6b427f9aab5d0a1d0a1a28_0.geojson
geojson-to-sqlite boston.db neighborhoods neighborhoods.geojson

(The command above uses Spatialite, but that's not required.)

Start up datasette and navigate to the neighborhoods table.

datasette serve boston.db

# in another terminal tab
open http://localhost:8001/boston/neighborhoods

You should see a map centered on Boston with each neighborhood outlined. Clicking a boundary will bring up a popup with details on that feature.

This plugin relies on (and will install) datasette-geojson. Any query that includes a geometry column will produce a map of the results. This also includes single row views.

Run the included demo project to see it live.

Configuration

This project uses the same map configuration as datasette-cluster-map. Here's how you would use Stamen's terrain tiles:

plugins:
  datasette-geojson-map:
    tile_layer: https://stamen-tiles-{s}.a.ssl.fastly.net/terrain/{z}/{x}/{y}.{ext}
    tile_layer_options:
      attribution: >-
        Map tiles by <a href=""http://stamen.com"">Stamen Design</a>, 
        under <a href=""http://creativecommons.org/licenses/by/3.0"">CC BY 3.0</a>. 
        Data by <a href=""http://openstreetmap.org"">OpenStreetMap</a>, 
        under <a href=""http://www.openstreetmap.org/copyright"">ODbL</a>.
      subdomains: abcd
      minZoom: 1
      maxZoom: 16
      ext: jpg

Options:

Styling map features

Map features can be styled using the simplestyle-spec. This requires setting specific fields on returned rows. Here's an example:

SELECT Name, geometry, ""#ff0000"" as fill, ""#0000ff"" as stroke, 0.2 as stroke-width,  from neighborhoods

That will render a neighborhood map where each polygon is filled in red, outlined in blue and lines are 0.2 pixels wide.

A more useful approach would use the CASE statement to color features based on data:

SELECT
  Name,
  geometry,
  CASE
    Name
    WHEN ""Roslindale"" THEN ""#ff0000""
    WHEN ""Dorchester"" THEN ""#0000ff""
    ELSE ""#dddddd""
  END fill
FROM
  neighborhoods

This will fill Roslindale in red, Dorchester in blue and all other neighborhoods in gray.

Development

To set up this plugin locally, first checkout the code. Then create a new virtual environment:

cd datasette-geojson-map
python3 -mvenv venv
source venv/bin/activate

Or if you are using pipenv:

pipenv shell

Now install the dependencies and test dependencies:

pip install -e '.[test]'

To run the tests:

pytest
",1,public,0,,,