我(大多数情况下)遵循了Per Wagner Nielsen的出色教程,但随后尝试(但失败了)向表单添加布尔字段。即使默认值为False并且在表单提交时未选中该复选框,使用“注册”表单创建的每个用户似乎都将布尔值设置为True。我使用登录控制器if user.is_admin()
中的行进行测试,并且该控制器确实返回user is admin
。我显示所有代码是因为我真的看不到我的错误在哪里-如果太多的话,抱歉。任何帮助将不胜感激。
app.py
from flask import Flask, reque,st, render_template, redirect, url_for, flash, g
from forms import SignupForm, LoginForm
from flask_sqlalchemy import SQLAlchemy
from flask_login import LoginManager, login_user, login_required, logout_user
from flask.ext.login import current_user
app = Flask(__name__)
app.secret_key = 'A0Zr98j/3yX R~XHH!jmN]LWX/,?RT'
app.config['SQLALCHEMY_DATABASE_URI'] = 'sqlite:///db.sqlite'
app.config['SQLALCHEMY_COMMIT_ON_TEARDOWN'] = True
db = SQLAlchemy(app)
login_manager = LoginManager()
login_manager.init_app(app)
######################################################################
# Models
######################################################################
class User(db.Model):
email = db.Column(db.String(80), primary_key=True, unique=True)
password = db.Column(db.String(80))
is_admin = db.Column(db.Boolean, default=False)
def __init__(self, email, password, is_admin):
self.email = email
self.password = password
self.is_admin = is_admin
def is_authenticated(self):
return True
def is_active(self):
return True
def is_anonymous(self):
return False
def get_id(self):
return str(self.email)
def is_admin(self):
if self.is_admin:
return True
else:
return False
def __repr__(self):
return '<User %r>' % self.email
######################################################################
@login_manager.user_loader
def load_user(email):
return User.query.filter_by(email = email).first()
@app.before_request
def before_request():
g.user = current_user
######################################################################
# Routes
######################################################################
@app.route('/')
def index():
return "Welcome to Flask"
@app.route('/signup', methods=['GET', 'POST'])
def signup():
form = SignupForm()
if request.method == 'GET':
return render_template('signup.html', form = form)
elif request.method == 'POST':
if form.validate_on_submit():
if User.query.filter_by(email=form.email.data).first():
return "Email address already exists"
else:
newuser = User(form.email.data, form.password.data, form.is_admin.data)
db.session.add(newuser)
db.session.commit()
return "User created"
else:
#return "Form didn't validate"
return render_template('signup.html', form=form)
@app.route('/login', methods=['GET','POST'])
def login():
form = LoginForm()
if request.method == 'GET':
return render_template('login.html', form=form)
elif request.method == 'POST':
if form.validate_on_submit():
user=User.query.filter_by(email=form.email.data).first()
if user:
if user.password == form.password.data:
login_user(user)
#return "User logged in"
if user.is_admin():
return "user is admin"
else:
return "user is not admin"
else:
return "Wrong password"
else:
return "user doesn't exist"
else:
return "form not validated"
@app.route("/logout")
@login_required
def logout():
logout_user()
return "Logged out"
@app.route('/protected')
@login_required
def protected():
return "protected area, user: " + current_user.email + ", " + str(g.user.is_admin)
######################################################################
if __name__ == '__main__':
app.run(host='0.0.0.0', port=80, debug=True)
forms.py
from flask_wtf import FlaskForm
from wtforms import StringField, PasswordField, SubmitField, validators, BooleanField
from wtforms.validators import Email, DataRequired
class SignupForm(FlaskForm):
email = StringField('Email',
[DataRequired(),Email()])
password = PasswordField(
'Password',
[DataRequired()])
is_admin = BooleanField('Is an Admin')
submit = SubmitField("Sign In")
class LoginForm(FlaskForm):
email = StringField('Email',
[DataRequired(),Email()])
password = PasswordField(
'Password',
[DataRequired()])
submit = SubmitField("Sign In")
templates / signup.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Access</title>
</head>
<body>
<h1>Sign-up</h1>
<form method="POST" action="/signup">
{{ form.hidden_tag() }}
{{ form.email.label }} {{ form.email(size=20) }}<br>
{{ form.password.label }} {{ form.password(size=20) }}<br>
{{ form.is_admin.label }} {{ form.is_admin() }}<br>
<input type="submit" value="Signup">
</form>
<h1>Form Errors</h1>
{{ form.errors }}
</body>
</html>
templates / login.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Login</title>
</head>
<body>
<h1>Login</h1>
<form method="POST" action="/login">
{{ form.hidden_tag() }}
{{ form.email.label }} {{ form.email(size=20) }}
{{ form.password.label }} {{ form.password(size=20) }}
<input type="submit" value="login">
</form>
</body>
</html>
答案 0 :(得分:2)
问题出在以下事实:模型类中有一个列is_admin
和一个名为is_admin()
的函数。在Python中,如果要为类变量和类方法使用相同的名称,请you better know what you are doing(但不要)。
为避免这种情况,您可以将函数is_admin()
重命名为is_administrator()
。
但是,如果考虑一下,直接在视图函数中评估字段,而不必声明类方法将更加容易:
if user.is_admin:
return "user is admin"
else:
return "user is not admin"
我还建议研究SQL Expression and Mapped Attributes,以更好地了解模型中所有这些类方法的作用。