diff --git a/pgml-dashboard/app/models.py b/pgml-dashboard/app/models.py index 01d87ac78..3928fad8a 100644 --- a/pgml-dashboard/app/models.py +++ b/pgml-dashboard/app/models.py @@ -318,17 +318,20 @@ class UploadedData(models.Model): created_at = models.DateTimeField(auto_now_add=True) updated_at = models.DateTimeField(auto_now=True) - def create_table(self, file): + def create_table(self, file, has_header=False): if file.content_type == "text/csv": reader = csv.reader(codecs.iterdecode(file, "utf-8")) headers = next(reader) - columns = ", ".join(map(lambda x: f"{x.replace(' ', '_').lower()} FLOAT4", headers)) + + if has_header: + columns = ", ".join(map(lambda x: f"{x.replace(' ', '_').lower()} TEXT", headers)) + else: + columns = ", ".join(map(lambda x: f"column_{x} TEXT", range(len(headers)))) with transaction.atomic(): sql = f"CREATE TABLE data_{self.pk} (" + columns + ")" with connection.cursor() as cursor: cursor.execute(sql) - file.seek(0) - cursor.copy_expert(f"COPY data_{self.pk} FROM STDIN CSV HEADER", file) + cursor.copy_expert(f"COPY data_{self.pk} FROM STDIN CSV {'HEADER' if has_header else ''}", file) diff --git a/pgml-dashboard/app/static/css/base.css b/pgml-dashboard/app/static/css/base.css index ef09a57ce..29ee3e955 100644 --- a/pgml-dashboard/app/static/css/base.css +++ b/pgml-dashboard/app/static/css/base.css @@ -685,3 +685,39 @@ body.uploader section li { body.uploader strong { font-weight: bold; } + +body.uploader label { + user-select: none; + cursor: pointer; +} + +/* + * Checkbox + */ +input[type=checkbox] { + /* Reset style */ + appearance: none; + + background: transparent; + border: 1px solid var(--gray-5); + + height: 1.6em; + width: 1.6em; + + border-radius: 3px; + + display: inline-flex; + align-items: center; + justify-content: center; + position: relative; + + cursor: pointer; +} + +input[type=checkbox]:checked:after { + content: '\2714'; + font-size: 1em; + position: absolute; + color: var(--highlite-green); + filter: brightness(0.75); +} diff --git a/pgml-dashboard/app/templates/uploader/index.html b/pgml-dashboard/app/templates/uploader/index.html index e0d01aee7..ef3921e79 100644 --- a/pgml-dashboard/app/templates/uploader/index.html +++ b/pgml-dashboard/app/templates/uploader/index.html @@ -11,15 +11,13 @@

cloud_uploadUpload Data

{% endif %} {% if error %} -

Hmm, something went wrong. Please make sure:

+

Hmm, something went wrong. Make sure:

{% else %} -

You can upload your datasets using the CSV format. Before uploading, please make sure:

+

You can upload your datasets using the CSV format. Before uploading, make sure:

{% endif %}
    -
  1. The data is numeric (i.e. only floats or integers and no text)
  2. -
  3. The CSV includes headers on the first line
  4. -
  5. The headers are alphanumeric, contain no spaces and don't start with a number
  6. +
  7. If the CSV has a header, the column names are alphanumeric, contain no spaces and don't start with a number
  8. The CSV is comma (,) delimited
@@ -30,7 +28,7 @@

Error:

{% endif %} -

If you are exporting data from a PostgreSQL database, you can use psql to generate a valid CSV file:

+

If you are exporting data from a PostgreSQL database, you can use psql to generate a valid CSV file with a header:

\copy your_table_name TO 'output.csv' CSV HEADER
@@ -40,8 +38,12 @@

Error:

{% csrf_token %} -
+
+
+ + +
diff --git a/pgml-dashboard/app/templates/uploader/uploaded.html b/pgml-dashboard/app/templates/uploader/uploaded.html index 5afd00f37..cb7a4b648 100644 --- a/pgml-dashboard/app/templates/uploader/uploaded.html +++ b/pgml-dashboard/app/templates/uploader/uploaded.html @@ -15,10 +15,21 @@

data_arrayPreview

table_rowsNext Steps

-

Your data has been saved in pgml.{{ table_name }} table.

-

You can now build a model using a Notebook or browse the data in the Console:

+

Your data has been saved in pgml.{{ table_name }} table. You can explore the data in the Console:

SELECT * FROM pgml.{{ table_name }}
+LIMIT 10
+
+

All columns were converted to text, so you'll need to cast them to the appropriate data type before training a model, for example:

+
+
CREATE MATERIALIZED VIEW pgml.{{ table_name }}_view AS
+SELECT {% for column in columns %}
+  CAST({{ column }} AS FLOAT4){% if not forloop.last %},{% else %}
+{% endif %}{% endfor %}FROM pgml.{{ table_name }}
+
+

You can now run experiments and build models using Notebooks:

+
+
SELECT * FROM pgml.{{ table_name }}_view
 LIMIT 10
diff --git a/pgml-dashboard/app/views/console.py b/pgml-dashboard/app/views/console.py index 1702fc03a..5650f8b56 100644 --- a/pgml-dashboard/app/views/console.py +++ b/pgml-dashboard/app/views/console.py @@ -48,16 +48,20 @@ def run_sql(request): try: cursor.execute("SET statement_timeout = '30s'") cursor.execute(query) - results = cursor.fetchall() - return render( - request, - "projects/sample.html", - { - "columns": [desc[0] for desc in cursor.description], - "rows": results, - }, - ) + if cursor.description: + results = cursor.fetchall() + + return render( + request, + "projects/sample.html", + { + "columns": [desc[0] for desc in cursor.description], + "rows": results, + }, + ) + else: + raise Exception(str(cursor.statusmessage)) except Exception as e: return HttpResponse( f""" diff --git a/pgml-dashboard/app/views/uploader.py b/pgml-dashboard/app/views/uploader.py index 5be820559..6771f4303 100644 --- a/pgml-dashboard/app/views/uploader.py +++ b/pgml-dashboard/app/views/uploader.py @@ -14,6 +14,7 @@ class UploadForm(forms.Form): file = forms.FileField() + has_header = forms.BooleanField(required=False) def index(request): @@ -31,7 +32,7 @@ def index(request): file_type=1 if file.content_type == "text/csv" else 2, ) - upload.create_table(file) + upload.create_table(file, form.cleaned_data.get("has_header", False)) except Exception as e: return render( request, pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy