我正在努力修改cookiecutter Flask应用。我尝试按https://realpython.com/blog/python/handling-email-confirmation-in-flask/添加电子邮件授权。
我的用户模型位于屏幕截图中,并且还是:
class User(UserMixin, SurrogatePK, Model):
__tablename__ = 'users'
username = Column(db.String(80), nullable=True)
email = Column(db.String(80), nullable=False)
#: The hashed password
password = Column(db.String(128), nullable=True)
created_at = Column(db.DateTime, nullable=False, default=dt.datetime.utcnow)
first_name = Column(db.String(30), nullable=True)
last_name = Column(db.String(30), nullable=True)
active = Column(db.Boolean(), default=False)
admin = Column(db.Boolean(), default=False)
confirmed = db.Column(db.Boolean, default=False)
confirmed_on = db.Column(db.DateTime, nullable=True)
def __init__(self, username=username, email=email, password=None, **kwargs):
db.Model.__init__(self, username=username, email=email, **kwargs)
if password:
self.set_password(password)
else:
self.password = None
def set_password(self, password):
self.password = bcrypt.generate_password_hash(password)
作为注册过程的一部分,我收到来自表单的电子邮件并处理它从中创建令牌并创建用户,然后使用以下方式向电子邮件发送确认电子邮件:
@blueprint.route("/get_email/", methods=['GET', 'POST'])
def get_email():
form = EmailForm(request.form, csrf_enabled=False)
if form.validate_on_submit():
new_user = User.create(username=None,email=form.email.data)
token = generate_confirmation_token(form.email.data)
confirm_url = url_for('user.confirm_email', token=token, _external=True)
html = render_template('users/activate.html', confirm_url=confirm_url)
subject = "Please confirm your email"
send_email(form.email.data, subject, html)
return redirect(url_for("main.home"))
在这种情况下,我发送了一封电子邮件至:
cluemarine5@mailinator.com
该电子邮件包含一个如下所示的确认链接:
http://127.0.0.1:5000/users/confirm/ImNsdWVtYXJpbmU1QG1haWxpbmF0b3IuY29tIg.CZ-urA.n5IErF0CPPG6EnIwJeSP6mPmDb4
其中包含嵌入的电子邮件' cluemarine5@mailinator.com'在令牌中。
确认您点击激活以下路线的链接:
@blueprint.route('/confirm/<token>')
def confirm_email(token):
try:
email = confirm_token(token)
except:
flash('The confirmation link is invalid or has expired.', 'danger')
user = User.query.filter_by(email=email).first_or_404()
if user.confirmed:
flash('Account already confirmed. Please login.', 'success')
else:
user.confirmed = True
user.confirmed_on = datetime.datetime.now()
db.session.add(user)
db.session.commit()
flash('You have confirmed your account. Thanks!', 'success')
return redirect(url_for('main.home'))
关于调试代码的工作正常,直到
db.session.commit()
然后我得到上面的错误。我做错了什么?
答案 0 :(得分:0)
我终于意识到这个cookiecutter正在使用一个名为'CRUDMixin'的类来进行db操作,它位于database.py中:
class CRUDMixin(object):
"""Mixin that adds convenience methods for CRUD (create, read, update, delete)
operations.
"""
@classmethod
def create(cls, **kwargs):
"""Create a new record and save it the database."""
instance = cls(**kwargs)
return instance.save()
def update(self, commit=True, **kwargs):
"""Update specific fields of a record."""
for attr, value in kwargs.iteritems():
setattr(self, attr, value)
return commit and self.save() or self
def save(self, commit=True):
"""Save the record."""
db.session.add(self)
if commit:
db.session.commit()
return self
def delete(self, commit=True):
"""Remove the record from the database."""
db.session.delete(self)
return commit and db.session.commit()
class Model(CRUDMixin, db.Model):
"""Base model class that includes CRUD convenience methods."""
__abstract__ = True
然后我改变了:
db.session.add(user)
db.session.commit()
要:
use.save()
它开始工作