From 9eb0ea26879fcd10281611728b7f9ddfcb088121 Mon Sep 17 00:00:00 2001 From: Frederick Muriuki Muriithi Date: Tue, 24 Sep 2024 14:23:13 -0500 Subject: Implement creation of new platform. --- uploader/platforms/models.py | 56 ++++++++++++++++++++++- uploader/platforms/views.py | 46 +++++++++++++++++-- uploader/templates/platforms/create-platform.html | 21 +++++++++ 3 files changed, 119 insertions(+), 4 deletions(-) (limited to 'uploader') diff --git a/uploader/platforms/models.py b/uploader/platforms/models.py index 4b690bb..199f2df 100644 --- a/uploader/platforms/models.py +++ b/uploader/platforms/models.py @@ -2,7 +2,7 @@ from typing import Optional import MySQLdb as mdb -from MySQLdb.cursors import DictCursor +from MySQLdb.cursors import Cursor, DictCursor def platforms_by_species( conn: mdb.Connection, @@ -29,6 +29,7 @@ def species_platforms_count(conn: mdb.Connection, species_id: int) -> int: (species_id,)) return int(cursor.fetchone()["count"]) + def platform_by_id(conn: mdb.Connection, platformid: int) -> Optional[dict]: """Retrieve a platform by its ID""" with conn.cursor(cursorclass=DictCursor) as cursor: @@ -39,3 +40,56 @@ def platform_by_id(conn: mdb.Connection, platformid: int) -> Optional[dict]: return dict(result) return None + + +def platform_by_species_and_id( + conn: mdb.Connection, species_id: int, platformid: int +) -> Optional[dict]: + """Retrieve a platform by its species and ID""" + with conn.cursor(cursorclass=DictCursor) as cursor: + cursor.execute("SELECT * FROM GeneChip WHERE SpeciesId=%s AND Id=%s", + (species_id, platformid)) + result = cursor.fetchone() + if bool(result): + return dict(result) + + return None + + +def save_new_platform(# pylint: disable=[too-many-arguments] + cursor: Cursor, + species_id: int, + geo_platform: str, + platform_name: str, + platform_shortname: str, + platform_title: str, + go_tree_value: Optional[str] +) -> dict: + """Save a new platform to the database.""" + params = { + "species_id": species_id, + "GeoPlatform": geo_platform, + "GeneChipName": platform_name, + "Name": platform_shortname, + "Title": platform_title, + "GO_tree_value": go_tree_value + } + cursor.execute("SELECT SpeciesId, GeoPlatform FROM GeneChip") + assert (species_id, geo_platform) not in ( + (row["SpeciesId"], row["GeoPlatform"]) for row in cursor.fetchall()) + cursor.execute( + "INSERT INTO " + "GeneChip(SpeciesId, GeneChipName, Name, GeoPlatform, Title, GO_tree_value) " + "VALUES(" + "%(species_id)s, %(GeneChipName)s, %(Name)s, %(GeoPlatform)s, " + "%(Title)s, %(GO_tree_value)s" + ")", + params) + new_id = cursor.lastrowid + cursor.execute("UPDATE GeneChip SET GeneChipId=%s WHERE Id=%s", + (new_id, new_id)) + return { + **params, + "Id": new_id, + "GeneChipId": new_id + } diff --git a/uploader/platforms/views.py b/uploader/platforms/views.py index 1abf52e..1030b6c 100644 --- a/uploader/platforms/views.py +++ b/uploader/platforms/views.py @@ -1,4 +1,5 @@ """The endpoints for the platforms""" +from MySQLdb.cursors import DictCursor from flask import ( flash, request, @@ -13,7 +14,10 @@ from uploader.db_utils import database_connection from uploader.species.models import all_species, species_by_id from uploader.datautils import safe_int, order_by_family, enumerate_sequence -from .models import platforms_by_species, species_platforms_count +from .models import (save_new_platform, + platforms_by_species, + species_platforms_count, + platform_by_species_and_id) platformsbp = Blueprint("platforms", __name__) render_template = make_template_renderer("platforms") @@ -69,7 +73,8 @@ def list_platforms(species_id: int): @require_login def create_platform(species_id: int): """Create a new genetic sequencing platform.""" - with database_connection(app.config["SQL_URI"]) as conn: + with (database_connection(app.config["SQL_URI"]) as conn, + conn.cursor(cursorclass=DictCursor) as cursor): species = species_by_id(conn, species_id) if not bool(species): flash("No species provided.", "alert-danger") @@ -81,4 +86,39 @@ def create_platform(species_id: int): species=species, activelink="create-platform") - raise NotImplementedError("This still needs to be implemented.") + try: + form = request.form + new_platform = save_new_platform( + cursor, + species_id, + form["geo-platform"], + form["platform-name"], + form["platform-shortname"], + form["platform-title"], + form.get("go-tree-value") or None) + except KeyError as _kerr: + flash(f"Required value for field {_kerr.args[0]} was not provided.", + "alert-danger") + return redirect(url_for("species.platforms.create_platform", + species_id=species_id)) + except AssertionError as _aerr: + flash(f"Platform with GeoPlatform value of '{form['geo-platform']}'" + f" already existst for species '{species['FullName']}'.", + "alert-danger") + return redirect(url_for("species.platforms.create_platform", + species_id=species_id)) + + flash("Platform created successfully", "alert-success") + return redirect(url_for("species.platforms.view_platform", + species_id=species_id, + platform_id=new_platform["Id"])) + + +@platformsbp.route("/platforms//view", + methods=["GET"]) +@require_login +def view_platform(species_id: int, platform_id: int): + """View details for a specific platform.""" + with database_connection(app.config["SQL_URI"]) as conn: + return platform_by_species_and_id( + conn, species_id, platform_id) diff --git a/uploader/templates/platforms/create-platform.html b/uploader/templates/platforms/create-platform.html index b5961ce..0866d5e 100644 --- a/uploader/templates/platforms/create-platform.html +++ b/uploader/templates/platforms/create-platform.html @@ -89,6 +89,27 @@ Name above.

+
+ + + +

This is a Chip identification value useful for analysis with the + + GeneWeaver + and + + WebGestalt + tools.
+ This can be left blank for custom platforms.

+
+