diff options
Diffstat (limited to 'app/routes.py')
-rw-r--r-- | app/routes.py | 215 |
1 files changed, 215 insertions, 0 deletions
diff --git a/app/routes.py b/app/routes.py new file mode 100644 index 0000000..d2bd3f0 --- /dev/null +++ b/app/routes.py @@ -0,0 +1,215 @@ +""" +routes.py module +---------------- + +This Python module contains the logic supporting: +1. Navigating between website pages +2. Interpreting user requests to the server +3. Dispatching requested content back to the user + +Python dependencies: +- flask: provides web application features +- forms: provides secure user form submission +- sqlalchemy: provides communication with database on server. + +Personal imports: +These are used to avoid cluttering this file with +placeholder data for posts' content. +""" + + +from flask import Flask, render_template, request, redirect, flash, url_for, jsonify +from flask_sqlalchemy import SQLAlchemy +from flask_bootstrap import Bootstrap + +from flask_wtf import FlaskForm +from wtforms import ( + SubmitField, + SelectField, + RadioField, + HiddenField, + StringField, + IntegerField, + FloatField, +) +from wtforms.validators import InputRequired, Length, Regexp, NumberRange +from datetime import datetime + +import placeholders as p + +app = Flask(__name__) + +# Flask-Bootstrap requires this line +Bootstrap(app) + + +# Flask-WTF encryption key +app.config["SECRET_KEY"] = "Scooby_Lu,_where_are_you?" + +# Our database name +db_name = "fapg.db" +app.config["SQLALCHEMY_DATABASE_URI"] = "sqlite:///" + db_name +app.config["SQLALCHEMY_TRACK_MODIFICATIONS"] = True +db = SQLAlchemy(app) + + +class Users(db.Model): + id = db.Column(db.Integer, primary_key=True) + name_first = db.Column(db.String(20), nullable=False) + name_last = db.Column(db.String(20), nullable=False) + email = db.Column(db.String(20), nullable=False) + phone_mobile = db.Column(db.Integer, nullable=False) + phone_alternative = db.Column(db.Integer) + updated = db.Column(db.String) + + def __init__( + self, name_first, name_last, email, phone_mobile, phone_alternative, updated + ): + self.name_first = name_first + self.name_last = name_last + self.email = email + self.phone_mobile = phone_mobile + self.phone_alternative = phone_alternative + self.updated = updated + + def __repr__(self): + return f"<User {self.name_first} {self.name_last}>" + + +class Products(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(20), nullable=False) + supplier = db.Column(db.String(20), nullable=False) + price = db.Column(db.Float(10), nullable=False) + updated = db.Column(db.String) + + def __init__(self, name, supplier, price, updated): + self.name = name + self.supplier = supplier + self.price = price + self.updated = updated + + def __repr__(self): + return f"<Product {self.name} by {self.supplier}>" + + +class Projects(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(20), nullable=False) + name_full = db.Column(db.String(20), nullable=False) + nickname = db.Column(db.String(20), nullable=False) + city = db.Column(db.String(20), nullable=False) + + def __repr__(self): + return f"<Project {self.name}>" + + +class Modules(db.Model): + id = db.Column(db.Integer, primary_key=True) + name = db.Column(db.String(20), unique=True, nullable=False) + description = db.Column(db.String(50), nullable=False) + + def __init__(self, name, description, updated): + self.name = name + self.description = description + self.updated = updated + + def __repr__(self): + return f"<Module {self.name}>" + + +class AddProduct(FlaskForm): + # id used only by update/edit + id = HiddenField() + name = StringField("Product name", validators=[InputRequired()]) + supplier = SelectField( + "Choose a supplier", + choices=[ + ("", ""), + ("Mister Brown", "Mister Brown"), + ("Madame Cerise", "Madame Cerise"), + ("Biton la Malice", "G. Biton la Malice"), + ("Leroy Merlin", "Leroy Merlin"), + ("other", "Other"), + ], + ) + price = FloatField("Retail price per unit") + # updated - date - handled in the route function + updated = HiddenField() + submit = SubmitField("Add/Update Product") + + +# add a new product to the database +@app.route("/add_product", methods=["GET", "POST"]) +def add_product(): + form = AddProduct() + if form.validate_on_submit(): + name = request.form["name"] + supplier = request.form["supplier"] + price = request.form["price"] + # get today's date from function, above all the routes + updated = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + # the data to be inserted into FAPG model - the table, products + record = Products(name, supplier, price, updated) + # Flask-SQLAlchemy magic adds record to database + db.session.add(record) + db.session.commit() + # create a message to send to the template + message = f"The data for product {name} has been submitted." + return render_template("add_product.html", message=message) + else: + # show validaton errors + # see https://pythonprogramming.net/flash-flask-tutorial/ + for field, errors in form.errors.items(): + for error in errors: + flash( + "Error in {}: {}".format(getattr(form, field).label.text, error), + "error", + ) + return render_template("add_product.html", form=form) + + +@app.route("/") +@app.route("/fapg/home") +def project(): + """This is our project welcome page.""" + michel = Users( + name_first="Michel", + name_last="Peter", + email="le-boss@fapg.com", + phone_mobile="00000000", + phone_alternative="0000000000", + updated="2022-04-21", + ) + modules = Modules.query.all() + print(module.name for module in modules) + return render_template("home.html", user=michel, project=fapg, modules=modules) + + +@app.route("/module/<module>") +def render_module(module): + modules = Modules.query.all() + catalog = Products.query.all() + user_modules = [module.name for module in modules] + print(user_modules) + # If a module was purchased by a user and added to their database, + # they have access to the corresponding module route. + if module in user_modules: + return render_template( + f"modules/{module}.html", + modules=modules, + catalog=catalog, + ) + else: + return render_template("errors/module-not-found.html", module=module) + + +# If this file is executed as a script (i.e. double-clicked), +# the Python interpreter will run the Flask process and begin serving +# the web pages on the standard localhost address (127.0.0.1). +# But if this file is called as a module by another Python script, it will not +# serve content to the web pages, but the function definitions contained in +# this file will be available to the calling script. +# E.g. calling script will know what the yes() function is. +if __name__ == "__main__": + app.run(debug=True) |