{"html_url": "https://github.com/simonw/datasette/issues/878#issuecomment-803473015", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/878", "id": 803473015, "node_id": "MDEyOklzc3VlQ29tbWVudDgwMzQ3MzAxNQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-03-20T22:33:05Z", "updated_at": "2021-03-20T22:33:05Z", "author_association": "OWNER", "body": "Things this mechanism needs to be able to support:\r\n\r\n- Returning a default JSON representation\r\n- Defining \"extra\" JSON representations blocks, which can be requested using `?_extra=`\r\n- Returning rendered HTML, based on the default JSON + one or more extras + a template\r\n- Using Datasette output renderers to return e.g. CSV data\r\n- Potentially also supporting streaming output renderers for streaming CSV/TSV/JSON-nl etc", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 648435885, "label": "New pattern for views that return either JSON or HTML, available for plugins"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/878#issuecomment-803472595", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/878", "id": 803472595, "node_id": "MDEyOklzc3VlQ29tbWVudDgwMzQ3MjU5NQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-03-20T22:28:12Z", "updated_at": "2021-03-20T22:28:12Z", "author_association": "OWNER", "body": "Another idea I had: a view is a class that takes the `datasette` instance in its constructor, and defines a `__call__` method that accepts a request and returns a response. Except `await __call__` looks like it might be a bit messy, discussion in https://github.com/encode/starlette/issues/886", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 648435885, "label": "New pattern for views that return either JSON or HTML, available for plugins"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/878#issuecomment-803472278", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/878", "id": 803472278, "node_id": "MDEyOklzc3VlQ29tbWVudDgwMzQ3MjI3OA==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-03-20T22:25:04Z", "updated_at": "2021-03-20T22:25:04Z", "author_association": "OWNER", "body": "I came up with a slightly wild idea for this that would involve pytest-style dependency injection.\r\n\r\nPrototype here: https://gist.github.com/simonw/496b24fdad44f6f8b7237fe394a0ced7\r\n\r\nCopying from my private notes:\r\n\r\n> Use the lazy evaluated DI mechanism to break up table view into different pieces eg for faceting\r\n> \r\n> Use that to solve JSON vs HTML views\r\n> \r\n> Oh here's an idea: what if the various components of the table view were each defined as async functions.... and then executed using asyncio.gather in order to run the SQL queries in parallel? Then try benchmarking with different numbers of threads?\r\n> \r\n> The async_call_with_arguments function could do this automatically for any awaitable dependencies\r\n> \r\n> This would give me massively parallel dependency injection\r\n> \r\n> (I could build an entire framework around this and call it c64)\r\n> \r\n> Idea: arguments called eg \"count\" are executed and the result passed to the function. If called count_fn then a reference to the not-yet-called function is passed instead \r\n> \r\n> I'm not going to completely combine the views mechanism and the render hooks. Instead, the core view will define a bunch of functions used to compose the page and the render hook will have conditional access to those functions - which will otherwise be asyncio.gather executed directly by the HTML page version\r\n> \r\n> Using asyncio.gather to execute facets and suggest facets in parallel would be VERY interesting \r\n> \r\n> suggest facets should be VERY cachable - doesn't matter if it's wrong unlike actual facets themselves\r\n> \r\n> What if all Datasette views were defined in terms of dependency injection - and those dependency functions could themselves depend on others just like pytest fixtures. Everything would become composable and async stuff could execute in parallel\r\n> \r\n> FURTHER IDEA: use this for the ?_extra= mechanism as well.\r\n> \r\n> Any view in Datasette can be defined as a collection of named keys. Each of those keys maps to a function or an async function that accepts as input other named keys, using DI to handle them.\r\n> \r\n> The HTML view is a defined function. So are the other outputs.\r\n> \r\n> Default original inputs include \u201crequest\u201d and \u201cdatasette\u201d.\r\n> \r\n> So\u2026 maybe a view function is a class methods that use DI. One of those methods as an .html() method used for the default page.\r\n> \r\n> Output formats are a bit more complicated because they are supposed to be defined separately in plugins. They are unified across query, row and table though.\r\n> \r\n> I\u2019m going to try breaking up the TableView to see what happens.", "reactions": "{\"total_count\": 1, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 1}", "issue": {"value": 648435885, "label": "New pattern for views that return either JSON or HTML, available for plugins"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/878#issuecomment-803471917", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/878", "id": 803471917, "node_id": "MDEyOklzc3VlQ29tbWVudDgwMzQ3MTkxNw==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2021-03-20T22:21:33Z", "updated_at": "2021-03-20T22:21:33Z", "author_association": "OWNER", "body": "This has been blocking things for too long.\r\n\r\nIf this becomes a documented pattern, things like adding a JSON output to https://github.com/dogsheep/dogsheep-beta becomes easier too.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 648435885, "label": "New pattern for views that return either JSON or HTML, available for plugins"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/878#issuecomment-709503359", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/878", "id": 709503359, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwMzM1OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:15:28Z", "updated_at": "2020-10-15T18:15:28Z", "author_association": "OWNER", "body": "I think this is blocking #619", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 648435885, "label": "New pattern for views that return either JSON or HTML, available for plugins"}, "performed_via_github_app": null} {"html_url": "https://github.com/simonw/datasette/issues/878#issuecomment-709502889", "issue_url": "https://api.github.com/repos/simonw/datasette/issues/878", "id": 709502889, "node_id": "MDEyOklzc3VlQ29tbWVudDcwOTUwMjg4OQ==", "user": {"value": 9599, "label": "simonw"}, "created_at": "2020-10-15T18:14:34Z", "updated_at": "2020-10-15T18:14:34Z", "author_association": "OWNER", "body": "The `BaseView` class does this for Datasette internals at the moment, but I'm not convinced it works as well as it could.\r\n\r\nI'd like to turn this into a class that is documented and available to plugins as well.", "reactions": "{\"total_count\": 0, \"+1\": 0, \"-1\": 0, \"laugh\": 0, \"hooray\": 0, \"confused\": 0, \"heart\": 0, \"rocket\": 0, \"eyes\": 0}", "issue": {"value": 648435885, "label": "New pattern for views that return either JSON or HTML, available for plugins"}, "performed_via_github_app": null}