Heroku defaults to 127.0.0.01 on page change

  flask, heroku, python, sqlalchemy

I’m having some trouble deploying my Flask App to Heroku. After a few tutorials I managed to get my Flask App hosted on Heroku, but I can’t access any other pages. It reaches the homepage on https://todoapplication-464425.herokuapp.com/, but when I try and change to the Login/Register/Logout then it just defaults back to 127.0.0.1:5000. Does anyone know a workaround for this?

Flask App

## Imports ##
from types import MethodDescriptorType
from flask import Flask
from flask import redirect
from flask import url_for
from flask import render_template
from flask import request
from flask import session
from flask import flash
from datetime import time, timedelta
import sqlite3
from logging import FileHandler, WARNING
from flask.helpers import make_response
from flask_sqlalchemy import SQLAlchemy

#Website Configuration
app = Flask(__name__)
app.debug = True
app.secret_key = "380r28br7328rv732c09"
app.permanent_session_lifetime = timedelta(minutes=5) #Session length - 5 minutes
file_handler = FileHandler('errorlogs.txt') #View error logs if they don't show in terminal
file_handler.setLevel(WARNING)
app.logger.addHandler(file_handler)
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///todo.db'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True #Removes annoying text
db = SQLAlchemy(app)

## SQL Database ##
def createUserTable():
  conn = sqlite3.connect('ToDoList.db')
  c = conn.cursor()
  c.execute('''CREATE TABLE User (
                id INTEGER PRIMARY KEY AUTOINCREMENT,
                firstName text NOT NULL,
                lastName text NOT NULL,
                email text NOT NULL,
                password TEXT NOT NULL )
                            ''') 
  conn.commit()
  conn.close()

#db.create_all()

#ToDoList Class
class Task(db.Model):
    id = db.Column(db.Integer, primary_key=True)
    chore = db.Column(db.Text)
    done = db.Column(db.Boolean, default=False) #SQlite doesn't have boolean properties - Second db made with SQLAchemy so strikethrough works
    email = db.Column(db.Text)

    def __init__(self, chore, email):
        self.chore = chore
        self.done = False
        self.email = email

    def __repr__(self):
        return '<chore %s>' % self.chore

#db.create_all()

## Website ##
@app.route("/")
def home():
  return render_template("index.html")

@app.route("/login", methods=["POST", "GET"])
def login():
  if request.method == "GET": #If webpage is retrieved and no info has been sent - just displays login page
    return render_template('login.html')
  else:
    email = request.form["email"]
    password = request.form["password"]
    with sqlite3.connect("ToDoList.db") as connection:
      c = connection.cursor()
      c.execute("SELECT * FROM User WHERE email= ? AND password= ? ;", (email, password)) #Selects from User table once registered
      result = c.fetchone()  #Grabs db row with full user info
      if result:
        session['name'] = result[1]  #Index [1] means it skips ID(0) and grabs name, then surname with [2]
        session['surname'] = result[2]
        session['email'] = email[3]
        session.permanent = True #Creates session for user
        loggedIn = make_response(render_template("todolist.html", name=session["name"], surname=session["surname"], email=session['email'])) #Passes three variables to todolist.html
        return loggedIn
    resp = make_response(render_template('login.html'))
    return resp

@app.route("/logout")
def logout():
  if "user" in session:
    user = session["name"]  #If session is active - Removes user from session
    userSurname = session["surname"]
    flash("You've been logged out", "info") #Flash is used for messages to be displayed
    session.pop(session["name"], None)
    session.pop(session["surname"], None)
  return redirect(url_for("login"))

@app.route("/register", methods =['GET', 'POST']) #Both get and post for form data to be sent
def register():
  if request.method == 'GET':
    return render_template("register.html")
  else:
    firstName = request.form["firstName"]
    lastName = request.form["lastName"]
    email = request.form["email"]
    password = request.form["password"]
  with sqlite3.connect("ToDoList.db") as connection: #Section below adds user to database
    c = connection.cursor()
    c.execute
    c.execute("INSERT INTO User (firstName, LastName, email, password) VALUES (?, ?, ?, ?);", (firstName,lastName, email, password))
    connection.commit()
  flash("You've been successfully registered", "info")
  return render_template('login.html')

@app.route("/todolist")
def todolist():
  tasks = Task.query.all() #Grabs all tasks
  userEmail=session['email']
  userTasks = Task.query.filter_by(email=userEmail).all() #Filters the results by email - All tasks held in same database
  return render_template('todolist.html', tasks=tasks, userTasks=userTasks, name=session["name"], surname=session["surname"], email=session['email']) #Keeps user displayed at top of page

@app.route('/task', methods=['POST'])
def add_task():
    email = session['email']
    chore = request.form['chore'] #Grabs user input from todolist page - saves as chore and updates sqlalchemy db
    task = Task(chore, email)
    db.session.add(task) #Adds then commits to save
    db.session.commit()
    return redirect(url_for('todolist')) #url_for saves and refreshes the page with new info - returns same page back

@app.route('/delete/<int:task_id>') #<int:task_id> allows us to pass a variable inside instead of a static html page - immediately redirects to todolist
def delete_task(task_id):
    task = Task.query.get(task_id)
    db.session.delete(task)
    db.session.commit()
    return redirect(url_for('todolist'))

@app.route('/done/<int:task_id>')
def resolve_task(task_id):
    task = Task.query.get(task_id)
    if task.done:
        task.done = False
    else:
        task.done = True
    db.session.commit()
    return redirect(url_for('todolist'))

## Redirects ##
@app.route("/admin")
def admin():
  return redirect(url_for("home"))
@app.route("/home")
def homepage():
  return redirect(url_for("home"))
@app.route("/todolist")
def emailcheck():
  if session['name'] not in session:
    return redirect(url_for("home"))

## Start application ##
if __name__ == "__main__":
  app.run(debug=True)

Procfile

web: gunicorn App:app

Requirements.txt

Flask==1.0.2
Flask-SQLAlchemy==2.5.
gunicorn==20.1.0
Jinja2==2.11.3
MarkupSafe==1.1.1
SQLAlchemy==1.4.15
virtualenv==20.4.6
Werkzeug==1.0.1

Folder setup

Source: Python Questions

LEAVE A COMMENT