Python 302需要登录的问题
我在Heroku上运行烧瓶应用程序时遇到问题。在本地运行时,该应用程序允许我登录并浏览导航栏选项。当我通过Heroku在线运行它时,最终会出现302代码,它会将我踢出登录屏幕,然后再次单击“登录”,它会将我带回主页(/index) 我已经设置了密钥,但我不确定还能做什么。请在此处查看应用程序() 有关Helper.py,请参见此处Python 302需要登录的问题,python,heroku,flask,sqlalchemy,Python,Heroku,Flask,Sqlalchemy,我在Heroku上运行烧瓶应用程序时遇到问题。在本地运行时,该应用程序允许我登录并浏览导航栏选项。当我通过Heroku在线运行它时,最终会出现302代码,它会将我踢出登录屏幕,然后再次单击“登录”,它会将我带回主页(/index) 我已经设置了密钥,但我不确定还能做什么。请在此处查看应用程序() 有关Helper.py,请参见此处 import os import requests import urllib.parse from flask import redirect, render_t
import os
import requests
import urllib.parse
from flask import redirect, render_template, request, session
from functools import wraps
def login_required(f):
"""
Decorate routes to require login.
http://flask.pocoo.org/docs/1.0/patterns/viewdecorators/
"""
@wraps(f)
def decorated_function(*args, **kwargs):
if session.get("user_id") is None:
return redirect("/")
return f(*args, **kwargs)
return decorated_function
# allows user to call stocks based on symbol
def lookup(symbol):
"""Look up quote for symbol."""
os.system("export API_KEY="+"pk_0d1467f2aeb748d0b81f445f22bd6665")
# Contact API
try:
api_key = os.environ.get("API_KEY")
response = requests.get(f"https://cloud-sse.iexapis.com/stable/stock/{urllib.parse.quote_plus(symbol)}/quote?token={api_key}")
response.raise_for_status()
except requests.RequestException:
return None
# Parse response
try:
quote = response.json()
return {
"name": quote["companyName"],
"price": float(quote["latestPrice"]),
"symbol": quote["symbol"]
}
except (KeyError, TypeError, ValueError):
return None
def usd(value):
"""Format value as USD."""
return f"${value:,.2f}"
主应用程序.py
import os
from flask import Flask, flash, jsonify, redirect, render_template, request, session
from flask_session import Session
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy import func
from tempfile import mkdtemp
from werkzeug.exceptions import default_exceptions, HTTPException, InternalServerError
from werkzeug.security import check_password_hash, generate_password_hash
from datetime import datetime
from helpers import login_required, lookup, usd
# Configure application
app = Flask(__name__)
app.config['SECRET_KEY'] = 'f3cfe9ed8fae309f02079dbf'
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
app.config['SQLALCHEMY_DATABASE_URI'] = os.environ['DATABASE_URL']
# calls SQLAlchemy database
db = SQLAlchemy(app)
# defines table values
class User(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
password = db.Column(db.String(120), unique=True, nullable=False)
cash = db.Column(db.Float(7), nullable=False)
remainder = db.Column(db.Float(7), nullable=False)
class Transactions(db.Model):
id = db.Column(db.Integer, primary_key=True)
username = db.Column(db.String(80), unique=True, nullable=False)
stockname = db.Column(db.String(80), unique=True, nullable=False)
stocksymbol = db.Column(db.String(80), unique=True, nullable=False)
stockprice = db.Column(db.Float(7), nullable=False)
stockshares = db.Column(db.Integer, nullable=False)
stocktotal = db.Column(db.Float(7), nullable=False)
class History(db.Model):
datetime = db.Column(db.DateTime(), primary_key=True)
username = db.Column(db.String(80), nullable=False)
buysell = db.Column(db.String(4), nullable=False)
stockname = db.Column(db.String(80), nullable=False)
stocksymbol = db.Column(db.String(80), nullable=False)
stockprice = db.Column(db.Float(7), nullable=False)
stockshares = db.Column(db.Float(7), nullable=False)
# Ensure templates are auto-reloaded
app.config["TEMPLATES_AUTO_RELOAD"] = True
# Ensure responses aren't cached
@app.after_request
def after_request(response):
response.headers["Cache-Control"] = "no-cache, no-store, must-revalidate"
response.headers["Expires"] = 0
response.headers["Pragma"] = "no-cache"
return response
# Custom filter
app.jinja_env.filters["usd"] = usd
# Configure session to use filesystem (instead of signed cookies)
app.config["SESSION_FILE_DIR"] = mkdtemp()
app.config["SESSION_PERMANENT"] = False
app.config["SESSION_TYPE"] = "filesystem"
Session(app)
# Make sure API key is set
if not os.environ.get("API_KEY"):
#set up api key for the stock quote engine
try:
os.environ["API_KEY"] = "pk_0d1467f2aeb748d0b81f445f22bd6665"
except:
raise RuntimeError("API_KEY not set")
@app.route("/register", methods=["GET", "POST"])
def register():
"""Register user"""
# User reached route via GET (as by clicking a link or via redirect)
if request.method == "GET":
return render_template("register.html")
# User reached route via POST (as by submitting a form via POST)
elif request.method == "POST":
# retrieve user entered information
username = request.form.get("username")
password = request.form.get("password")
confirmation = request.form.get("confirmation")
# Query database for username
user = User.query.filter_by(username=username).first()
# Enter valid username
if not username:
flash("Please enter a username")
return redirect("/register")
# Enter valid password
elif not password:
flash("Please enter a password")
return redirect("/register")
# Password was not confirmed
elif not confirmation:
flash("Please confirm password")
return redirect("/register")
# Ensure passwords match
elif password != confirmation:
flash("Passwords do not match")
return redirect("/register")
# if username is taken
elif user:
flash("Username is already taken")
return redirect("/register")
# saves password to hash
password = generate_password_hash(password)
# adds username, password, cash available and remainder to table
db.session.add(User(username=username,password=password,cash=10000,remainder=10000))
db.session.commit()
# Save user id into session
# Do not change to session["user_id"] = user; for some reason website does not run properly
session["user_id"] = User.query.filter_by(username=username).first()
# Redirect user to home page
return redirect("/index")
@app.route("/", methods=["GET", "POST"])
def login():
"""Log user in"""
# User reached route via GET (as by clicking a link or via redirect)
if request.method == "GET":
return render_template("login.html")
# User reached route via POST (as by submitting a form via POST)
if request.method == "POST":
# calls entered username and password
username = request.form.get("username")
password = request.form.get("password")
# finds entered username in database
user = User.query.filter_by(username=username).first()
# Ensure username was submitted
if not username:
flash("Please provide username")
return redirect("/")
# Ensure password was submitted
elif not password:
flash("Please provide password")
return redirect("/")
# Ensure username exists and password is correct
elif not user:
flash("Invalid username")
return redirect("/")
elif not check_password_hash(user.password, password):
flash("Invalid password")
return redirect("/")
# Remember which user has logged in
# Do not change to session["user_id"] = user; for some reason website does not run properly
session["user_id"] = user
# Redirect user to home page
return redirect("/index")
@app.route("/logout")
def logout():
"""Log user out"""
# Forget any user_id
session.clear()
# Redirect user to login form
return redirect("/")
@app.route("/index")
@login_required
def index():
"""Show portfolio of stocks"""
"""
worked
session["user_id"]
#calls current user
username = session["user_id"]
"""
#calls current user
username = session["user_id"]
# calls total investments for current user
total = username.cash
# calls remaining cash for current user
remainder = username.remainder
# tries calling transactions for current user
try:
# initializes transactions table for current user
transactions = Transactions.query.filter_by(username=username.username)
# totals all stock investments for current user
stocktotal = transactions.with_entities(func.sum(Transactions.stocktotal).label("total")).first().total
# calculates remainder amount of cash
remainder = total - stocktotal
# updates remainder
username.remainder = remainder
db.session.commit()
# if new user then defaults to this
except:
# calculates total stocks invested based on cash total and remainder; for a new user it will always be 0
stocktotal = total - remainder
# returns html template
return render_template("index.html", total=total, remainder=remainder, transactions=transactions, stocktotal=stocktotal)