|
@@ -1,210 +1,157 @@
|
|
|
-from flask import Flask, abort, jsonify, url_for, render_template, g, request
|
|
|
-from flask.json import JSONEncoder
|
|
|
+# File Name: app.py
|
|
|
+# Author Name: In-young Choung
|
|
|
+# Date: March 1, 2017
|
|
|
+# Description: This python file contains database configuration and creates database tables and fields using flask_sqlalchemy.
|
|
|
+# Users' values passed from Javascript are inserted into the database table.
|
|
|
+# It also has mapping request to interact with specific html files and
|
|
|
+# it reads a file of itemlist.text and prints out to the console.
|
|
|
+
|
|
|
from flask_sqlalchemy import SQLAlchemy
|
|
|
-from flask_httpauth import HTTPBasicAuth
|
|
|
-import decimal, re, json
|
|
|
-from passlib.apps import custom_app_context as pwd_context
|
|
|
-from itsdangerous import (TimedJSONWebSignatureSerializer as Serializer, BadSignature, SignatureExpired)
|
|
|
+from flask import Flask, render_template, request
|
|
|
+
|
|
|
|
|
|
+# passing the whole app code to Flask
|
|
|
app = Flask(__name__)
|
|
|
-#Configuration for Database ORM
|
|
|
+
|
|
|
+# Configuration for Database ORM - database name: grocery app, user: groceryadmin, password: VKov2q3XTtqj6w9o
|
|
|
app.config['SQLALCHEMY_DATABASE_URI'] = 'postgresql://groceryadmin:VKov2q3XTtqj6w9o@localhost/groceryapp'
|
|
|
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
|
|
|
+
|
|
|
+# Database instantiation
|
|
|
db = SQLAlchemy(app)
|
|
|
|
|
|
-app.config['SECRET_KEY'] = 'geunyeorang cheoeum daehoa sijag hajamaja'
|
|
|
-auth = HTTPBasicAuth()
|
|
|
+# database ORM calc table - 3 columns
|
|
|
+class Calc(db.Model):
|
|
|
+ __tablename__="calc"
|
|
|
|
|
|
+ # database fields
|
|
|
+ id = db.Column(db.Integer, primary_key=True)
|
|
|
+ result = db.Column(db.String(64))
|
|
|
+ timestampe = db.Column(db.TIMESTAMP)
|
|
|
+
|
|
|
+ # adding constraints to delete all data in Item when calc is deleted.
|
|
|
+ item = db.relationship('Item', backref='calc', cascade='all, delete-orphan', lazy='dynamic')
|
|
|
|
|
|
-#This helper class will be used to facilitate the printing of database objects as strings
|
|
|
-# class MJSONEncoder(JSONEncoder):
|
|
|
-# def default(self, obj):
|
|
|
-# if isinstance(obj, decimal.Decimal):
|
|
|
-# # Convert decimal instances to strings.
|
|
|
-# return str(obj)
|
|
|
-# return super(MJSONEncoder, self).default(obj)
|
|
|
-#
|
|
|
-#
|
|
|
-# app.json_encoder = MJSONEncoder
|
|
|
|
|
|
+# database ORM item table - 9 columns
|
|
|
+class Item(db.Model):
|
|
|
+ __tablename__ = "items"
|
|
|
|
|
|
-class User(db.Model):
|
|
|
- __tablename__ = "users"
|
|
|
+ # database fields
|
|
|
id = db.Column(db.Integer, primary_key=True)
|
|
|
- email = db.Column(db.String(120), unique=True)
|
|
|
- password_hash = db.Column(db.String(128))
|
|
|
-
|
|
|
- def hash_password(self, password):
|
|
|
- self.password_hash = pwd_context.encrypt(password)
|
|
|
- print(self.password_hash)
|
|
|
-
|
|
|
- def verify_password(self, password):
|
|
|
- return pwd_context.verify(password, self.password_hash)
|
|
|
-
|
|
|
- def generate_auth_token(self, expiration=600):
|
|
|
- s = Serializer(app.config['SECRET_KEY'], expires_in=expiration)
|
|
|
- return s.dumps({'id': self.id})
|
|
|
-
|
|
|
- @staticmethod
|
|
|
- def verify_auth_token(token):
|
|
|
- print ('48 - ' + token)
|
|
|
- s = Serializer(app.config['SECRET_KEY'])
|
|
|
- try:
|
|
|
- data = s.loads(token)
|
|
|
- except SignatureExpired:
|
|
|
- return None # valid token, but expired
|
|
|
- except BadSignature:
|
|
|
- return None # invalid token
|
|
|
- user = User.query.get(data['id'])
|
|
|
- if user is None:
|
|
|
- return
|
|
|
- return user
|
|
|
-
|
|
|
-
|
|
|
-
|
|
|
-@auth.verify_password
|
|
|
-def verify_password(email_or_token, password):
|
|
|
- # first try to authenticate by token
|
|
|
- user = User.verify_auth_token(email_or_token)
|
|
|
- if not user:
|
|
|
- # try to authenticate with username/password
|
|
|
- user = User.query.filter_by(email=email_or_token).first()
|
|
|
- print ('86')
|
|
|
- print (user)
|
|
|
- if not user or not user.verify_password(password):
|
|
|
- return False
|
|
|
- g.user = user
|
|
|
- return True
|
|
|
+ item_type = db.Column(db.String(64))
|
|
|
+ brand_name = db.Column(db.String(64))
|
|
|
+ price = db.Column(db.Integer)
|
|
|
+ weight = db.Column(db.Integer)
|
|
|
+ weight_type = db.Column(db.String(5))
|
|
|
+ discount = db.Column(db.Integer)
|
|
|
+ discount_type = db.Column(db.String(20))
|
|
|
+ calc_id = db.Column(db.Integer, db.ForeignKey(Calc.id))
|
|
|
+
|
|
|
+
|
|
|
+# create all the tables defined as classes
|
|
|
+db.create_all()
|
|
|
|
|
|
|
|
|
+# mapping request to URLs
|
|
|
@app.route('/', methods = ['GET', 'POST'])
|
|
|
def index():
|
|
|
- if request.method == 'POST':
|
|
|
- if request.form['submit'] == 'calculate_btn':
|
|
|
- weight1 = request.form['weight1']
|
|
|
- weight2 = request.form['weight2']
|
|
|
- print (weight1)
|
|
|
- print (weight2)
|
|
|
- # my_total = calculate(weight1, weight2)
|
|
|
- # print (my_total)
|
|
|
- my_total = 69
|
|
|
-
|
|
|
- return my_total
|
|
|
if request.method == 'GET':
|
|
|
+ # renders to html file
|
|
|
return render_template('index.html')
|
|
|
|
|
|
|
|
|
-
|
|
|
-
|
|
|
-@app.route('/calculate_total/', methods = ['GET'])
|
|
|
+# end point where python gets user data from javascript
|
|
|
+@app.route('/calculate', methods = ['GET'])
|
|
|
def calculate():
|
|
|
- print (request)
|
|
|
- print (request.view_args)
|
|
|
- item1 = (request.args.get('item1'))
|
|
|
- item2 = (request.args.get('item2'))
|
|
|
- price1 = (request.args.get('price1'))
|
|
|
- price2 = (request.args.get('price2'))
|
|
|
- weight1 = (request.args.get('weight1'))
|
|
|
- weight2 = (request.args.get('weight2'))
|
|
|
-
|
|
|
+ # get value from html
|
|
|
+ itemtype = (request.args.get('param1'))
|
|
|
+ brandN1 = (request.args.get('param2'))
|
|
|
+ brandN2 = (request.args.get('param3'))
|
|
|
+ price1 = (request.args.get('param4'))
|
|
|
+ price2 = (request.args.get('param5'))
|
|
|
+ weight1 = (request.args.get('param6'))
|
|
|
+ weightT1 = (request.args.get('param7'))
|
|
|
+ weight2 = (request.args.get('param8'))
|
|
|
+ weightT2 = (request.args.get('param9'))
|
|
|
+ discount1 = (request.args.get('param10'))
|
|
|
+ discountT1 = (request.args.get('param11'))
|
|
|
+ discount2 = (request.args.get('param12'))
|
|
|
+ discountT2 = (request.args.get('param13'))
|
|
|
+
|
|
|
+
|
|
|
+ #TODO: calculate function
|
|
|
# total2 = float(total)
|
|
|
# new_total = 1.0 + total2
|
|
|
# print(new_total)
|
|
|
-
|
|
|
- item1_byWeight = float(price1) / float(weight1);
|
|
|
- item2_byWeight = float(price2) / float(weight2);
|
|
|
-
|
|
|
- if (item1_byWeight < item2_byWeight) :
|
|
|
- difference = float(item2_byWeight) - float(item1_byWeight)
|
|
|
- result = (item1 + "is cheapter by " + difference)
|
|
|
- else :
|
|
|
- difference = float(item1_byWeight) - float(item2_byWeight)
|
|
|
- result = (item2 + "is cheapter by " + difference)
|
|
|
- print(result)
|
|
|
-
|
|
|
- return result
|
|
|
-
|
|
|
-
|
|
|
-def calculate(weight1, weight2):
|
|
|
- total = weight1 + weight2
|
|
|
- return total
|
|
|
-
|
|
|
-
|
|
|
-@app.route('/login', methods=['POST'])
|
|
|
-def login():
|
|
|
- if request.headers['content-Type'] == 'application/x-www-form-urlencoded':
|
|
|
- email = request.form['email']
|
|
|
- password = request.form['password']
|
|
|
- if email is None or password is None:
|
|
|
- abort(400)
|
|
|
- if User.query.filter_by(email=email).first() is not None:
|
|
|
- verify = verify_password(email, password)
|
|
|
- user = User(email=email)
|
|
|
- print('108 - ' + verify)
|
|
|
- if verify:
|
|
|
- print('You already in there\n')
|
|
|
- return render_template('success.html')
|
|
|
- else:
|
|
|
- print ('Login failed')
|
|
|
- return 'Login failed'
|
|
|
-
|
|
|
- user = User(email=email)
|
|
|
- User.hash_password(user, password)
|
|
|
- db.session.add(user)
|
|
|
+ #
|
|
|
+ # weight_types = ['lb', 'kg', 'g']
|
|
|
+ #
|
|
|
+ # item1_byWeight = float(price1) / float(weight1);
|
|
|
+ # item2_byWeight = float(price2) / float(weight2);
|
|
|
+ #
|
|
|
+ # if (item1_byWeight < item2_byWeight) :
|
|
|
+ # difference = float(item2_byWeight) - float(item1_byWeight)
|
|
|
+ # result = (item1 + "is cheapter by " + difference)
|
|
|
+ # else :
|
|
|
+ # difference = float(item1_byWeight) - float(item2_byWeight)
|
|
|
+ # result = (item2 + "is cheapter by " + difference)
|
|
|
+ #
|
|
|
+ # print(param1 + param2)
|
|
|
+ # result = param1 + param2
|
|
|
+
|
|
|
+ # returns a row from db
|
|
|
+ # item_from_db = Item.query.filter_by(item_type=itemtype).first();
|
|
|
+
|
|
|
+ # if item_from_db is not None:
|
|
|
+ # print("already exists in the database.")
|
|
|
+ # else:
|
|
|
+
|
|
|
+ try:
|
|
|
+ # define array variables to be ready to match with db columns
|
|
|
+ brand_names = [brandN1, brandN2]
|
|
|
+ prices = [price1, price2]
|
|
|
+ weights = [weight1, weight2]
|
|
|
+ weight_types = [weightT1, weightT2]
|
|
|
+ discounts = [discount1, discount2]
|
|
|
+ discount_types = [discountT1, discountT2]
|
|
|
+
|
|
|
+ # iteration variable for loop
|
|
|
+ i = 0
|
|
|
+
|
|
|
+ # loop twice to save two compared items into database
|
|
|
+ for i in range(0, 2):
|
|
|
+ item = Item(item_type = itemtype, brand_name = brand_names[i], price =prices[i],
|
|
|
+ weight=weights[i] , weight_type = weight_types[i], discount = discounts[i] ,
|
|
|
+ discount_type = discount_types[i])
|
|
|
+
|
|
|
+ # insert a new row into the database
|
|
|
+ db.session.add(item)
|
|
|
+
|
|
|
+ # write it to db disk once the loop is done
|
|
|
db.session.commit()
|
|
|
- return render_template('success.html')
|
|
|
- elif request.headers['Content-Type'] == 'application/json':
|
|
|
- print ('122')
|
|
|
- print(request.json)
|
|
|
- email = request.json.get('email')
|
|
|
- password = request.json.get('password')
|
|
|
- if email is None or password is None:
|
|
|
- abort(400)
|
|
|
- if User.query.filter_by(email=email).first() is not None:
|
|
|
- verify = verify_password(email, password)
|
|
|
- user = User(email=email)
|
|
|
- print ('130')
|
|
|
- print (verify)
|
|
|
- if verify:
|
|
|
- print (g.user.id)
|
|
|
- token = g.user.generate_auth_token(600)
|
|
|
- return jsonify({'email': user.email, 'authToken': token.decode('ascii')}), 201, {
|
|
|
- 'Location': url_for('get_user', id=g.user.id, _external=True)}
|
|
|
- else:
|
|
|
- print ('Error: Login Unsuccessful')
|
|
|
- return 'Error: Login Unsuccessful'
|
|
|
-
|
|
|
- user = User(email=email)
|
|
|
- User.hash_password(user, password)
|
|
|
- db.session.add(user)
|
|
|
- db.session.commit()
|
|
|
- verify_password(email, password)
|
|
|
- token = g.user.generate_auth_token(600)
|
|
|
- return jsonify({'email': user.email, 'authToken': token.decode('ascii')}), 201, {'Location': url_for('get_user', id=user.id, _external=True)}
|
|
|
-
|
|
|
-
|
|
|
-@app.route('/users/<int:id>')
|
|
|
-@auth.login_required
|
|
|
-def get_user(id):
|
|
|
- user = User.query.get(id)
|
|
|
- if not user:
|
|
|
- abort(400)
|
|
|
- return jsonify({'email': user.email, 'password': user.password_hash})
|
|
|
|
|
|
+ # catch the exception and print it
|
|
|
+ except ValueError:
|
|
|
+ print(ValueError)
|
|
|
+ print("failed to create new row")
|
|
|
|
|
|
-@app.route('/token')
|
|
|
-@auth.login_required
|
|
|
-def get_auth_token():
|
|
|
- token = g.user.generate_auth_token(600)
|
|
|
- return jsonify({'token': token.decode('ascii'), 'duration': 600})
|
|
|
|
|
|
+# File I/O - prints a list of grocery items
|
|
|
+path = "C:\In-young Choung\Computer Programming\Self Programming Files\grocerycalc\itemlist.txt"
|
|
|
+# open a file for writing and create it if it doesn't exist.
|
|
|
+f = open(path,"w+")
|
|
|
|
|
|
-@app.route('/resource')
|
|
|
-@auth.login_required
|
|
|
-def get_resource():
|
|
|
- return jsonify({'data': 'Hello, %s!' % g.user.email})
|
|
|
+# open the file in the defined path and "r" read it
|
|
|
+f = open(path, "r")
|
|
|
+if f.mode == 'r':
|
|
|
+ # use read function to read the entire file.
|
|
|
+ contents = f.read()
|
|
|
+ #print the file content in the console
|
|
|
+ print(contents)
|
|
|
|
|
|
|
|
|
+# main method
|
|
|
if __name__ == '__main__':
|
|
|
app.debug = True
|
|
|
# app.debug = False
|