issue_comments: 590607385
This data as json
html_url | issue_url | id | node_id | user | created_at | updated_at | author_association | body | reactions | issue | performed_via_github_app |
---|---|---|---|---|---|---|---|---|---|---|---|
https://github.com/simonw/datasette/pull/683#issuecomment-590607385 | https://api.github.com/repos/simonw/datasette/issues/683 | 590607385 | MDEyOklzc3VlQ29tbWVudDU5MDYwNzM4NQ== | 9599 | 2020-02-24T23:49:37Z | 2020-02-24T23:49:37Z | OWNER | Here's the `upload_csv.py` plugin file I've been playing with: ```python from datasette import hookimpl from starlette.responses import PlainTextResponse, HTMLResponse from starlette.endpoints import HTTPEndpoint import csv as csv_std import codecs import sqlite_utils class UploadApp(HTTPEndpoint): def __init__(self, scope, receive, send, datasette): self.datasette = datasette super().__init__(scope, receive, send) def get_database(self): # For the moment just use the first one that's not immutable mutable = [db for db in self.datasette.databases.values() if db.is_mutable] return mutable[0] async def get(self, request): return HTMLResponse( await self.datasette.render_template( "upload_csv.html", {"database_name": self.get_database().name} ) ) async def post(self, request): formdata = await request.form() csv = formdata["csv"] # csv.file is a SpooledTemporaryFile, I can read it directly filename = csv.filename # TODO: Support other encodings: reader = csv_std.reader(codecs.iterdecode(csv.file, "utf-8")) headers = next(reader) docs = (dict(zip(headers, row)) for row in reader) if filename.endswith(".csv"): filename = filename[:-4] # Import data into a table of that name using sqlite-utils db = self.get_database() def fn(conn): writable_conn = sqlite_utils.Database(db.path) writable_conn[filename].insert_all(docs, alter=True) return writable_conn[filename].count # Without block=True we may attempt 'select count(*) from ...' # before the table has been created by the write thread count = await db.execute_write_fn(fn, block=True) return HTMLResponse( await self.datasette.render_template( "upload_csv_done.html", { "database": self.get_database().name, "table": filename, "num_docs": count, }, ) ) @hookimpl def asgi_wrapper(datasette): def wrap_with_asgi_auth(app): async def wrapped_app(scope, recieve, send): if scope["path"] == "/-/upload-csv": await UploadApp(scope, recieve, send, datasette) else: await app(scope, recieve, send) return wrapped_app return wrap_with_asgi_auth ``` I also dropped copies of the two template files from https://github.com/simonw/datasette-upload-csvs/tree/699e6ca591f36264bfc8e590d877e6852f274beb/datasette_upload_csvs/templates into my `write-templates/` directory. | {"total_count": 0, "+1": 0, "-1": 0, "laugh": 0, "hooray": 0, "confused": 0, "heart": 0, "rocket": 0, "eyes": 0} | 570101428 |