diff options
Diffstat (limited to 'uploader/species')
| -rw-r--r-- | uploader/species/models.py | 61 | ||||
| -rw-r--r-- | uploader/species/views.py | 64 |
2 files changed, 106 insertions, 19 deletions
diff --git a/uploader/species/models.py b/uploader/species/models.py index 4426b64..acfa51e 100644 --- a/uploader/species/models.py +++ b/uploader/species/models.py @@ -28,7 +28,7 @@ def order_species_by_family(species: tuple[dict, ...]) -> list: **ordered, _key: ordered.get(_key, tuple()) + (current,) } - ordered = reduce(__order__, species, {}) + ordered = reduce(__order__, species, {})# type: ignore[var-annotated] return sorted(tuple(ordered.items()), key=lambda item: item[0][0]) @@ -47,7 +47,7 @@ def save_species(conn: mdb.Connection, common_name: str, scientific_name: str, family: str, - taxon_id: Optional[str] = None) -> int: + taxon_id: Optional[str] = None) -> dict: """ Save a new species to the database. @@ -58,17 +58,18 @@ def save_species(conn: mdb.Connection, common_name: The species' common name. scientific_name; The species' scientific name. """ - genus, species = scientific_name.split(" ") + genus, *species_parts = scientific_name.split(" ") + species_name: str = " ".join(species_parts) families = species_families(conn) with conn.cursor() as cursor: cursor.execute("SELECT MAX(OrderId) FROM Species") species = { "common_name": common_name, "common_name_lower": common_name.lower(), - "menu_name": f"{common_name} ({genus[0]}. {species.lower()})", + "menu_name": f"{common_name} ({genus[0]}. {species_name.lower()})", "scientific_name": scientific_name, "family": family, - "family_order": families[family], + "family_order": families.get(family, 999999), "taxon_id": taxon_id, "species_order": cursor.fetchone()[0] + 5 } @@ -91,6 +92,56 @@ def save_species(conn: mdb.Connection, } +def update_species(# pylint: disable=[too-many-arguments, too-many-positional-arguments] + conn: mdb.Connection, + species_id: int, + common_name: str, + scientific_name: str, + family: str, + family_order: int, + species_order: int +): + """Update a species' details. + + Parameters + ---------- + conn: A connection to the MariaDB database. + species_id: The species identifier + + Key-Word Arguments + ------------------ + common_name: A layman's name for the species + scientific_name: A binomial nomenclature name for the species + family: The grouping under which the species falls + family_order: The ordering for the "family" above + species_order: The ordering of this species in relation to others + """ + with conn.cursor(cursorclass=DictCursor) as cursor: + genus, *species_parts = scientific_name.split(" ") + species_name = " ".join(species_parts) + species = { + "species_id": species_id, + "common_name": common_name, + "common_name_lower": common_name.lower(), + "menu_name": f"{common_name} ({genus[0]}. {species_name.lower()})", + "scientific_name": scientific_name, + "family": family, + "family_order": family_order, + "species_order": species_order + } + cursor.execute( + "UPDATE Species SET " + "SpeciesName=%(common_name)s, " + "Name=%(common_name_lower)s, " + "MenuName=%(menu_name)s, " + "FullName=%(scientific_name)s, " + "Family=%(family)s, " + "FamilyOrderId=%(family_order)s, " + "OrderId=%(species_order)s " + "WHERE Id=%(species_id)s", + species) + + def species_families(conn: mdb.Connection) -> dict: """Retrieve the families under which species are grouped.""" with conn.cursor(cursorclass=DictCursor) as cursor: diff --git a/uploader/species/views.py b/uploader/species/views.py index f39ca98..4bfa7ae 100644 --- a/uploader/species/views.py +++ b/uploader/species/views.py @@ -1,47 +1,68 @@ """Endpoints handling species.""" +from markupsafe import escape from pymonad.either import Left, Right, Either +from gn_libs.mysqldb import database_connection from flask import (flash, request, - url_for, redirect, Blueprint, current_app as app) from uploader.population import popbp -from uploader.datautils import order_by_family +from uploader.platforms import platformsbp +from uploader.flask_extensions import url_for from uploader.ui import make_template_renderer -from uploader.db_utils import database_connection from uploader.oauth2.client import oauth2_get, oauth2_post from uploader.authorisation import require_login, require_token +from uploader.datautils import order_by_family, enumerate_sequence +from uploader.population.models import (populations_by_species, + population_by_species_and_id) -from .models import all_species, save_species, species_by_id, species_families +from .models import (all_species, + save_species, + species_by_id, + update_species, + species_families) speciesbp = Blueprint("species", __name__) speciesbp.register_blueprint(popbp, url_prefix="/") +speciesbp.register_blueprint(platformsbp, url_prefix="/") render_template = make_template_renderer("species") @speciesbp.route("/", methods=["GET"]) +@require_login def list_species(): """List and display all the species in the database.""" with database_connection(app.config["SQL_URI"]) as conn: return render_template("species/list-species.html", - allspecies=all_species(conn)) + allspecies=enumerate_sequence(all_species(conn))) @speciesbp.route("/<int:species_id>", methods=["GET"]) @require_login def view_species(species_id: int): """View details of a particular species and menus to act upon it.""" + streamlined_ui = request.args.get("streamlined_ui") with database_connection(app.config["SQL_URI"]) as conn: species = species_by_id(conn, species_id) if bool(species): - return render_template("species/view-species.html", - species=species, - activelink="view-species") + population = population_by_species_and_id( + conn, species_id, request.args.get("population_id")) + if bool(population): + return redirect(url_for("species.populations.view_population", + species_id=species_id, + population_id=population["Id"])) + return render_template( + "species/view-species.html", + species=species, + activelink="view-species", + populations=populations_by_species(conn, species["SpeciesId"])) flash("Could not find a species with the given identifier.", "alert-danger") - return redirect(url_for("species.view_species")) + return redirect(url_for("base.index" + if streamlined_ui + else "species.view_species")) @speciesbp.route("/create", methods=["GET", "POST"]) @require_login @@ -55,6 +76,8 @@ def create_species(): if request.method == "GET": return render_template("species/create-species.html", families=species_families(conn), + return_to=( + request.args.get("return_to") or ""), activelink="create-species") error = False @@ -72,7 +95,7 @@ def create_species(): error = True parts = tuple(name.strip() for name in scientific_name.split(" ")) - if len(parts) != 2 or not all(bool(name) for name in parts): + if (len(parts) != 2 and len(parts) != 3) or not all(bool(name) for name in parts): flash("The scientific name you provided is invalid.", "alert-danger") error = True @@ -106,7 +129,15 @@ def create_species(): species = save_species( conn, common_name, scientific_name, family, taxon_id) - flash("Species saved successfully!", "alert-success") + flash( + f"You have successfully added species " + f"'{escape(species['scientific_name'])} " + f"({escape(species['common_name'])})'.", + "alert-success") + + return_to = request.form.get("return_to").strip() + if return_to: + return redirect(url_for(return_to, species_id=species["species_id"])) return redirect(url_for("species.view_species", species_id=species["species_id"])) @@ -177,9 +208,14 @@ def edit_species_extra(token: dict, species_id: int):# pylint: disable=[unused-a ).either(__failure__, lambda res: res) if bool(species) and request.method == "POST": - flash("We would have edited the species, but the feature is not " - "currently implemented …", - "alert-danger") + update_species(conn, + species_id, + request.form["species_name"], + request.form["species_fullname"], + request.form["species_family"], + int(request.form["species_familyorderid"]), + int(request.form["species_orderid"])) + flash("Updated species successfully.", "alert-success") return redirect(url_for("species.edit_species_extra", species_id=species_id)) |
