From a3a95f636e1f1139b03e946b61a2047d708d14a5 Mon Sep 17 00:00:00 2001 From: Damien De Paoli Date: Tue, 12 Jan 2021 21:51:33 +1100 Subject: [PATCH] now have a Person class & associated CReate/Update/Delete functions, and menu in base.html --- main.py | 1 + person.py | 108 +++++++++++++++++++++++++++++++++++++++++ templates/base.html | 16 +++++- templates/person.html | 28 +++++++++++ templates/persons.html | 16 ++++++ 5 files changed, 168 insertions(+), 1 deletion(-) create mode 100644 person.py create mode 100644 templates/person.html create mode 100644 templates/persons.html diff --git a/main.py b/main.py index 748240f..df21d11 100644 --- a/main.py +++ b/main.py @@ -29,6 +29,7 @@ Bootstrap(app) ################################# Now, import non-book classes ################################### from settings import Settings from files import Files +from person import Person ####################################### GLOBALS ####################################### # allow jinja2 to call these python functions directly diff --git a/person.py b/person.py new file mode 100644 index 0000000..79b9a46 --- /dev/null +++ b/person.py @@ -0,0 +1,108 @@ +from wtforms import SubmitField, StringField, HiddenField, validators, Form +from flask_wtf import FlaskForm +from flask import request, render_template, redirect +from main import db, app, ma +from sqlalchemy import Sequence +from sqlalchemy.exc import SQLAlchemyError +from status import st, Status + +################################################################################ +# Class describing Person in the database, and via sqlalchemy, connected to the DB as well +################################################################################ +class Person(db.Model): + id = db.Column(db.Integer, db.Sequence('person_id_seq'), primary_key=True ) + tag = db.Column(db.String(48), unique=False, nullable=False) + surname = db.Column(db.String(48), unique=False, nullable=False) + firstname = db.Column(db.String(48), unique=False, nullable=False) + + def __repr__(self): + return "".format(self.tag,self.firstname, self.surname) + +################################################################################ +# Helper class that inherits a .dump() method to turn class Person into json / useful in jinja2 +################################################################################ +class PersonSchema(ma.SQLAlchemyAutoSchema): + class Meta: + model = Person + ordered = True + +################################################################################ +# Helper class that defines a form for person, used to make html
, with field validation (via wtforms) +################################################################################ +class PersonForm(FlaskForm): + id = HiddenField() + tag = StringField('Tag (searchable name):', [validators.DataRequired()]) + firstname = StringField('FirstName(s):', [validators.DataRequired()]) + surname = StringField('Surname:', [validators.DataRequired()]) + submit = SubmitField('Save' ) + delete = SubmitField('Delete' ) + +################################################################################ +# Routes for person data +# +# /persons -> GET only -> prints out list of all persons +################################################################################ +@app.route("/persons", methods=["GET"]) +def persons(): + persons = Person.query.all() + return render_template("persons.html", persons=persons, alert=st.GetAlert(), message=st.GetMessage() ) + + +################################################################################ +# /person -> GET/POST -> creates a new person type and when created, takes you back to /persons +################################################################################ +@app.route("/person", methods=["GET", "POST"]) +def new_person(): + form = PersonForm(request.form) + page_title='Create new Person' + if 'surname' not in request.form: + return render_template("person.html", form=form, page_title=page_title ) + else: + person = Person( tag=request.form["tag"], surname=request.form["surname"], firstname=request.form["firstname"] ) + try: + db.session.add(person) + db.session.commit() + print(person) + st.SetMessage( "Created new Person ({})".format(person.tag) ) + return redirect( '/persons' ) + except SQLAlchemyError as e: + st.SetAlert( "danger" ) + st.SetMessage( "Failed to add Person: {}".format(e.orig) ) + return render_template("person.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() ) + +################################################################################ +# /person/ -> GET/POST(save or delete) -> shows/edits/delets a single +# person +################################################################################ +@app.route("/person/", methods=["GET", "POST"]) +def person(id): + form = PersonForm(request.form) + page_title='Edit Person' + if request.method == 'POST': + try: + person = Person.query.get(id) + if 'delete' in request.form: + st.SetMessage("Successfully deleted Person: ({})".format( person.tag ) ) + person = Person.query.filter(Person.id==id).delete() + if 'submit' in request.form and form.validate(): + st.SetMessage("Successfully Updated Person: (From: {}, {}, {})".format(person.tag, person.firstname, person.surname) ) + person.tag = request.form['tag'] + person.surname = request.form['surname'] + person.firstname = request.form['firstname'] + st.AppendMessage(" To: ({}, {}, {})".format(person.tag, person.firstname, person.surname) ) + db.session.commit() + return redirect( '/persons' ) + except SQLAlchemyError as e: + st.SetAlert( "danger" ) + st.SetMessage( "Failed to modify Person: {}".format(e.orig) ) + return render_template("person.html", form=form, page_title=page_title, alert=st.GetAlert(), message=st.GetMessage() ) + else: + person = Person.query.get(id) + form = PersonForm(request.values, obj=person) + return render_template("person.html", object=person, form=form, page_title = page_title, alert=st.GetAlert(), message=st.GetMessage() ) + +################################################################################ +# helper fund to GetPersons -> person_list -> jinja2 for person drop-down in book.html +################################################################################ +def GetPersons(): + return Person.query.order_by('surname','firstname').all() diff --git a/templates/base.html b/templates/base.html index fb62788..97aaf3a 100644 --- a/templates/base.html +++ b/templates/base.html @@ -49,6 +49,20 @@ View Details + + - + diff --git a/templates/person.html b/templates/person.html new file mode 100644 index 0000000..8ace7b2 --- /dev/null +++ b/templates/person.html @@ -0,0 +1,28 @@ +{% extends "base.html" %} {% block main_content %} +
+

{{page_title}}

+
+
+ {% for field in form %} + {% if field.type == 'HiddenField' or field.type == 'CSRFTokenField' %} + {{field}}
+ {% elif field.type != 'SubmitField' %} +
+ {{ field.label( class="col-lg-4" ) }} + {{ field( class="form-control col-lg-4" ) }} +
+ {% endif %} + {% endfor %} +
+
+
+
+ {{ form.submit( class="btn btn-primary offset-lg-4 col-lg-2" )}} + {% if 'Edit' in page_title %} + {{ form.delete( class="btn btn-outline-danger col-lg-2" )}} + {% endif %} +
+
+
+
+{% endblock main_content %} diff --git a/templates/persons.html b/templates/persons.html new file mode 100644 index 0000000..e68328e --- /dev/null +++ b/templates/persons.html @@ -0,0 +1,16 @@ +{% extends "base.html" %} + +{% block main_content %} +

Show All People

+ + + + + + {% for person in persons %} + + + {% endfor %} + +
TagFirstname(s)Surname
{{person.tag}}{{person.firstname}}{{person.surname}}
+{% endblock main_content %}