Permalink
Cannot retrieve contributors at this time
Name already in use
A tag already exists with the provided branch name. Many Git commands accept both tag and branch names, so creating this branch may cause unexpected behavior. Are you sure you want to create this branch?
bookshop_project_A/homepage.py
Go to fileThis commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
178 lines (169 sloc)
7.48 KB
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from main import app | |
from flask import Flask, session, g, redirect, url_for, render_template, abort, flash, make_response, request | |
import os | |
import sqlite3 | |
from functools import wraps | |
# more extension types can be added to the array | |
EXTENSIONS = ['jpg', 'png'] | |
BOOK_COVERS = '/home/codio/workspace/main/static/book_covers' | |
app.config['BOOK_COVERS'] = BOOK_COVERS | |
# ALWAYS check user session | |
@app.before_request | |
def user_logged_in(): | |
user_id = session.get('access_mode') | |
if user_id is None: | |
# Session not found | |
g.user = None | |
else: | |
g.user= user_id | |
# Wrappers allow additional functionality | |
# Code inspired by https://flask.palletsprojects.com/en/2.0.x/patterns/viewdecorators/ | |
def login_req(view): | |
@wraps(view) | |
def wrapped_view(**kwargs): | |
# if no login | |
# massive help from https://www.programcreek.com/python/example/100778/flask.g.user | |
if g.user is None: | |
# login again | |
return redirect(url_for('login')) | |
return view(**kwargs) | |
# decorated func | |
return wrapped_view | |
# Wrapper | |
# Code inspired by https://flask.palletsprojects.com/en/2.0.x/patterns/viewdecorators/ | |
def admin_req(view): | |
@wraps(view) | |
def wrapped_view(**kwargs): | |
# check if user is admin | |
if g.user == 'admin': | |
# display view | |
return view(**kwargs) | |
if g.user is None: | |
return redirect(url_for('login')) # login again | |
# already logged in? | |
return redirect(url_for('homepage')) | |
return wrapped_view | |
@app.route('/homepage', methods=['GET','POST']) | |
@login_req | |
def homepage(): | |
if request.method == 'POST': | |
# doesnt show stock list unless session user is admin | |
if request.form['Submit'] == 'STOCK LEVELS': | |
return redirect(url_for('stock_levels')) | |
elif request.form['Submit'] == 'LOGOUT': | |
# Logout therefore remove everything from session | |
session.clear() | |
return redirect(url_for('login')) | |
elif request.form['Submit'] == 'CART': | |
# View shopping cart function | |
return redirect(url_for('shopping_cart')) #this function is located in checkout.py file | |
else: | |
# Connect to database and get ALL book data for ALL books | |
con = sqlite3.connect('bookshop_database.db') | |
cur = con.cursor() | |
cur.execute("SELECT * FROM books") | |
# Put into variable | |
rows = cur.fetchall() | |
# Render the homepage | |
return render_template('homepage.html',page=url_for('homepage'),books=rows) | |
# Add books to stock | |
@app.route('/homepage/add_book',methods = ['POST']) | |
def add_book(): | |
_isbn = request.form['isbn'] | |
con = sqlite3.connect('bookshop_database.db') | |
cur = con.cursor() | |
# Check if any existing row that has the same primary key (isbn13) | |
cur.execute("SELECT * FROM books WHERE isbn13=?;", [_isbn]) | |
row = cur.fetchone() | |
# session['book'] is nested dictionary | |
book_dict = {row[3]:{'title':row[0],'cover':row[5],'isbn':row[3],'price':row[7],'quantity':1,'total_individual_price' : row[7],'qty_left' : row[8],}} | |
if 'book' in session: | |
# If book isbn has already been added to the cart: | |
if row[3] in session['book']: # (row[3] is isbn number (PRIMARY KEY)) | |
# Quantity of same book + 1 | |
session['book'][row[3]]['quantity'] += 1 | |
# Add retail price to the existing total for that book | |
session['book'][row[3]]['total_individual_price'] += row[7] | |
# Update total cost of cart | |
session['total_price'] += row[7] | |
# Quantity + 1 | |
session['total_quantity'] += 1 | |
# Book with diff isbn13 number added to cart: | |
else: | |
# Add book to session dict | |
session['book'] = dict(list(session['book'].items())+list(book_dict.items())) | |
# Price of book added to order | |
session['total_price'] += row[7] | |
# Quantity + 1 | |
session['total_quantity'] += 1 | |
else: | |
# If no book has been added yet (notice quantity is set to 1) | |
session['book'] = book_dict | |
session['total_price'] = row[7] | |
session['total_quantity'] = 1 | |
return redirect(url_for('homepage')) | |
# Page for viewing stock (admin required) | |
# Template checks session for admin priviledges before this is run | |
@app.route('/homepage/stocklist', methods=['GET','POST']) | |
@admin_req | |
def stock_levels(): | |
if request.method == 'POST': | |
# 2 buttons (POST) | |
if request.form['Submit'] == 'ADD STOCK': | |
return redirect(url_for('add_stock')) | |
elif request.form['Submit'] == 'GO BACK': | |
return redirect(url_for('homepage')) | |
else: | |
# list all books from db if method not post (default) | |
con = sqlite3.connect('bookshop_database.db') | |
cur = con.cursor() | |
cur.execute("SELECT * FROM books") | |
rows = cur.fetchall() | |
con.close() | |
return render_template('stock_checker.html', page = url_for('stock_levels'), books = rows) | |
# Add new books or update if isbn (PK) is the same as existing | |
@app.route('/homepage/stocklist/add_stock', methods=['GET','POST']) | |
@admin_req | |
def add_stock(): | |
if request.method == 'POST': | |
if request.form['Submit'] == 'SUBMIT': | |
file = request.files["inpt_file"] | |
# When file uploaded is true | |
if file: # if the user had given us a file | |
# basic function to check if filetype is valid: | |
if allowed_file(file.filename): | |
filename = file.filename | |
# Save img file to book covers folder | |
file.save(os.path.join(app.config['BOOK_COVERS'],filename)) | |
con = sqlite3.connect('bookshop_database.db') | |
con.row_factory = lambda cursor, row: row[0] | |
cur = con.cursor() | |
# Check if book with same primary key exists | |
cur.execute("SELECT isbn13 FROM books WHERE isbn13=?",(request.form['isbn'],)) | |
row = cur.fetchall() | |
# If it does, before we insert we must delete the current row | |
if len(row) != 0: | |
cur.execute("DELETE FROM books WHERE isbn13=?",(request.form['isbn'],)) | |
# we add values that we provided in a form into our database | |
cur.execute("INSERT INTO books VALUES(?,?,?,?,?,?,?,?,?)",(request.form['book_title'],request.form['author'],request.form['pub_date'],request.form['isbn'],request.form['desc'],filename,request.form['trade_price'],request.form['retail_price'],request.form['qnty'])) | |
con.commit() | |
con.close() | |
# return to stock page with new stock details added | |
return redirect(url_for('stock_levels')) | |
flash('Bad file extension.') | |
# essentially try again | |
return redirect(url_for('add_stock')) | |
# essentially try again | |
flash('No image uploaded.') | |
return redirect(url_for('add_stock')) | |
else: | |
return render_template('add_edit_stock.html',page=url_for('add_stock')) | |
# use of rsplit taken from https://flask.palletsprojects.com/en/2.0.x/patterns/fileuploads/ | |
def allowed_file(filename): | |
# a '.' is required in order for it to be a valid filename | |
if '.' not in filename: | |
return False | |
# if there is a '.' then ANY of the allowed extensions | |
if filename.rsplit('.', 1)[1].lower() in EXTENSIONS: | |
return True | |
return False |