from flask import Flask, g, request, render_template, redirect, url_for, flash, abort
from flask_login import LoginManager, login_required, current_user, login_user, logout_user
from flask_bcrypt import check_password_hash, generate_password_hash
import models
import forms
app = Flask(__name__)
app.secret_key = 'Kajp5dp5#lA!px36A_!56a36sdAojko2iqnkm9_#^!62i'
DEBUG = True
PORT = 8000
HOST = '0.0.0.0'
# For bad URL requests out-ruling purposes
allowed_uri = ['index', 'login', 'register', 'logout', 'memo', 'view_memo', 'edit', 'settings']
login_manager = LoginManager()
login_manager.init_app(app)
login_manager.login_view = 'login'
login_manager.login_message_category = "warning"
@login_manager.user_loader
def load_user(userid):
try:
return models.User.get(models.User.id==userid)
except models.DoesNotExist:
return None
@app.before_request
def before_request():
g.db = models.DATABASE
g.db.connect()
g.user = current_user
@app.after_request
def after_request(response):
g.db.close()
return response
@app.route('/register', methods=['GET', 'POST'])
def register():
if not current_user.is_anonymous:
return redirect(url_for('index'))
form = forms.RegisterForm()
if form.validate_on_submit():
models.User.create_user(
username=form.username.data,
email=form.email.data,
password=form.password.data
)
flash("Please log in to start recording your memoirs.", "success")
flash("Registered successfully!", "success")
return redirect(url_for('index'))
return render_template('register.html', form=form)
@app.route('/login', methods=['GET', 'POST'])
def login():
error_in_login = False
if not current_user.is_anonymous:
return redirect(url_for('index'))
else:
form = forms.LoginForm()
if form.validate_on_submit():
try:
user = models.User.get(models.User.username == form.username.data)
except models.DoesNotExist:
error_in_login = True
flash("Username and password do not match!", "danger")
else:
if check_password_hash(user.password, form.password.data):
login_user(user)
flash("Welcome {}!".format(user.username), "success")
return redirect(url_for('index'))
else:
error_in_login = True
flash("Username and password do not match!", "danger")
return render_template('login.html', form=form, error_in_login=error_in_login)
@app.route('/logout')
@login_required
def logout():
logout_user()
return redirect(url_for('login'))
def getmemo_byid(memo_id):
try:
memo = models.Memo.select().where(models.Memo.id==memo_id).get()
except models.DoesNotExist:
abort(404)
else:
return memo
def filter_items(items_string, passed_model, memo):
item_list = [item.strip().lstrip().capitalize() for item in items_string.split(',') if item.strip().lstrip() != ""]
newly_created = []
old_counter = 0
for item_name in item_list:
#######flash("Item name: {}".format(item_name), "danger")
try:
newly_created.append( passed_model.create(name=item_name) )
except models.IntegrityError:
old_counter+=1
#######flash("{} old records found are {}".format(passed_model.__name__, old_counter), "warning")
#######flash("Newly created records for {} are {}".format(passed_model.__name__, len(newly_created)), "success")
return item_list
def record_items(item_list, modelitems, passed_model, memo):
# Clean list from removed old items
deleted_records = 0
for item in [item.item_name for item in modelitems.select().where(modelitems.memo==memo)]:
if item not in item_list:
try:
deleted_records += modelitems.get(modelitems.item_name==item, memo=memo).delete_instance()
except models.DoesNotExist:
flash("Could not delete! Record does not exist.", "danger")
#######flash("{} items removed from the {} bonds.".format(deleted_records, modelitems.__name__), "danger")
# Create new item bonds
created_records = 0
for item in item_list:
try:
item_name = passed_model.get(passed_model.name**item)
modelitems.create(memo=memo.id, item_name=item_name)
except models.IntegrityError:
flash("Bond between {} and \"{}\" memo already exists.".format(item, memo.title), "danger")
except ValueError:
flash("Error creating bond between {} and \"{}\" memo already exists.".format(item, memo.title), "danger")
else:
created_records+=1
#######flash("Congratulations! Item relation created.", "success")
#######flash("{} new created relations.".format(created_records), "success")
@app.route('/record', methods=['GET', 'POST'])
@login_required
def record(memo_id=None):
form = forms.MemoForm()
if form.validate_on_submit():
with g.db.transaction():
try:
memo = models.Memo.create(
user = g.user.id,
money_made = form.money_made.data.strip(),
content = form.content.data.replace('\n', ' ').replace('\r', '').strip()
)
if form.title.data != "":
memo.title = form.title.data.strip().lstrip()
memo.save()
food_list = filter_items(form.foods.data, models.Food, memo)
record_items(food_list, models.MemoFoods, models.Food, memo)
activ_list = filter_items(form.activities.data, models.Activity, memo)
record_items(activ_list, models.MemoActivities, models.Activity, memo)
except ValueError:
flash("Error recording memo!", "danger")
else:
if form.title.data.strip() != "":
flash("Memo \"{}\" recorded.".format(form.title.data), "success")
else:
flash("Memo recorded.".format(form.title.data), "success")
return redirect(url_for('index'))
return render_template('record.html', form=form)
@app.route('/edit/', methods=['GET', 'POST'])
@login_required
def edit(memo_id=None):
form = forms.MemoForm()
if form.validate_on_submit():
with g.db.transaction():
try:
models.Memo.update(
title= form.title.data.strip(),
user = g.user.id,
money_made = form.money_made.data.strip(),
content = form.content.data.replace('\n', ' ').replace('\r', '').strip()
).where(models.Memo.id==memo_id).execute()
memo = models.Memo.get(models.Memo.id==memo_id)
food_list = filter_items(form.foods.data, models.Food, memo)
record_items(food_list, models.MemoFoods, models.Food, memo)
activ_list = filter_items(form.activities.data, models.Activity, memo)
record_items(activ_list, models.MemoActivities, models.Activity, memo)
except ValueError:
flash("Error updating record!", "danger")
else:
flash("Memo \"{}\" updated!".format(form.title.data), "success")
return redirect(url_for('index'))
else:
memo = getmemo_byid(memo_id)
memo_items = {
'foods': [food.name for food in memo.foods()],
'activities': [activity.name for activity in memo.activities()]
}
return render_template('edit.html', form=form, memo=memo, memo_items=memo_items)
@app.route('/settings', methods=['GET', 'POST'])
@login_required
def settings():
form = forms.SettingsForm()
if form.validate_on_submit():
user = models.User.select().where(models.User.id==current_user.id).get()
if form.username.data.strip().lstrip().lower() != user.username.lower():
user.username = form.username.data.strip().lstrip()
if form.email.data.strip().lstrip().lower() != user.email.lower():
user.email = form.email.data.strip().lstrip()
if form.password.data != "" and check_password_hash(user.password, form.password.data):
user.password = generate_password_hash(form.new_password.data, 13)
user.save()
flash("User settings updated successfully!", "success")
else:
flash("Password is incorrect.", "danger")
return redirect(url_for('settings'))
return redirect(url_for('index'))
return render_template('settings.html', form=form)
@app.route('/test')
@login_required
def test():
memos = models.Memo.select().where(models.Memo.user==g.user.id).group_by(models.Memo.timestamp.year)
return render_template('test.html', memos=memos)
@app.route('/memos/---')
@login_required
def view_memo(year, month, day, memo_id):
memo = getmemo_byid(memo_id)
memo_foods = models.MemoFoods.select().where(models.MemoFoods.memo==memo)
food_list = [item.item_name.name for item in memo_foods]
memo_activs = models.MemoActivities.select().where(models.MemoActivities.memo==memo)
activ_list = [item.item_name.name for item in memo_activs]
return render_template("view_memo.html", memo=memo, food_list=food_list, activ_list=activ_list)
@app.route('/')
def index():
if not current_user.is_anonymous:
memoirs = current_user.get_memos().limit(10)
return render_template('index.html', memoirs=memoirs)
return redirect(url_for('login'))
@app.route('/memos')
@app.route('/memos/')
@app.route('/memos/-')
@app.route('/memos/--')
@app.route('/memos/---')
@login_required
def navigate(year=None, month=None, day=None, memo_id=None):
display_years, display_months, display_days = False, False, False
try:
# Display years
memoirs = (models.Memo
.select()
.where(models.Memo.user==g.user.id)
.group_by(models.Memo.timestamp.year)
)
display_years, display_months, display_days = True, False, False
if year != None:
# Display months
memoirs = models.Memo.select().where(
models.Memo.user==g.user._get_current_object(),
models.Memo.timestamp.year==year
).group_by(models.Memo.timestamp.month)
display_years, display_months, display_days = False, True, False
if month != None:
# Display days
memoirs = models.Memo.select().where(
models.Memo.user==g.user._get_current_object(),
models.Memo.timestamp.year==year,
models.Memo.timestamp.month==month
)
display_years, display_months, display_days = False, False, True
except models.DoesNotExist:
abort(404)
else:
return render_template('index.html',
memoirs=memoirs,
display_years=display_years,
display_months=display_months,
display_days=display_days)
@app.route('/erase/')
@login_required
def erase(memo_id):
try:
deleted_memo = models.Memo.get(
models.Memo.user==g.user.id,
models.Memo.id==memo_id
).delete_instance()
except models.DoesNotExist:
pass
else:
flash("Memo deleted.", "success")
return redirect(url_for('index'))
@app.errorhandler(404)
def not_found(error):
return render_template('404.html'), 404
if __name__ == '__main__':
models.initialize()
try:
models.User.create_user(
username="ProjectH",
email="your@email.com",
password="yourpassword",
admin=True
)
except ValueError:
pass
app.run(debug=DEBUG, port=PORT, host=HOST)